更改pandas Period和PeriodIndex的频率

时间:2018-03-04 20:42:52

标签: python pandas

我正在将一些具有年度报告信息的股票数据导入到pandas DataFrame中。但是年度报告结束日期的日期是奇数月(1月底),而不是年末。

years = ['2017-01-31', '2016-01-31', '2015-01-31']
df = pd.DataFrame(data = years, columns = ['years'])

df
Out[357]: 
        years
0  2017-01-31
1  2016-01-31
2  2015-01-31

当我尝试添加显示报告数据有效期的PeriodIndex时,默认为12月结束,而不是从日期字符串中推断

df.index = pd.PeriodIndex(df['years'], freq ='A')

df.index

Out[367]: PeriodIndex(['2017', '2016', '2015'], dtype='period[A-DEC]', 
name='years', freq='A-DEC')

请注意,频率应为'A-JAN'。

我认为这意味着无法从PeriodIndex和我给出的结束日期字符串推断出结束日期。

我可以使用asfreq方法更改它,并使用“A-JAN”作为频率字符串锚定偏移量anchored offsets。但是,这会更改PeriodIndex中的所有单个期间,而不是单独更改,因为年度报告的年度报告可以有不同的报告结束日期(如果公司更改了报告期间)。

有没有办法解释每个日期字符串并正确设置我的pandas框架中每一行的每个句点?

我的最终目标是设置一个周期列或索引,其频率为“年度”,但周期结束日期设置为年份对应行的日期。

**进一步扩展这个问题。考虑到我有许多股票,每个股票的年度财务数据为3 - 4年,所有股票的年度报告频率(或季度)都有不同的开始和结束日期。

Out[14]: 
        years tickers
0  2017-01-31      PG
1  2016-01-31      PG
2  2015-01-31      PG
3  2017-05-31       T
4  2016-05-31       T
5  2015-05-31       T

我想要的是一个具有正确Period对象的列,这些对象配置有正确的结束日期(来自年份列),并且所有具有年度频率。我已经考虑过迭代这些年来使用apply.map或lambda函数和pd.Period函数。可能是PeriodIndex不能与其中具有不同结束日期的不同Period对象一起存在。

之类的东西
for row in df.years:
    s.append(pd.Period(row, freq='A")
df['period']= s

1 个答案:

答案 0 :(得分:0)

@KRkirov让我思考。看起来,Period构造函数不够智能,无法通过读取日期字符串来设置频率的结束日期。我能够通过在报告期结束日期建立一个锚字符串来获得频率结束日期,如下所示:

# return a month in 3 letter abbreviation format (eg. "JAN")
df['offset'] = df['years'].dt.strftime('%b').str.upper()

# now build up an anchor offset string (eg. "A-JAN" )
# for quarterly report (eg. "Q-JAN") for q report ending January for year
df['offset_strings'] = "A" + '-' + df.offset

锚点字符串记录在pandas docs here中。

然后遍历DataFrame的行以构造每个Period并将其放入列表中,然后将Period对象列表(强制转换为PeriodIndex)添加到列中。

ps = []
for i, r in df.iterrows():
     p = pd.Period(r['years'], freq = r['offset_strings']))
     ps.append(p)
df['period'] = ps

这将返回正确的PeriodIndex并正确设置Period Objects:

df['period']
Out[40]: 
0   2017
1   2016
2   2015
Name: period, dtype: object

df['period'][0]
Out[41]: Period('2017', 'A-JAN')

df.index = df.period

df.index
Out[43]: PeriodIndex(['2017', '2016', '2015'], dtype='period[A-JAN]', 
name='period', freq='A-JAN')

不漂亮,但我找不到另一种方式。