如何在Pandas DataFrame索引中获取每个月的最后一天(使用TimeGrouper)

时间:2018-01-16 18:56:43

标签: python pandas pandas-groupby python-datetime datetimeindex

我有一个日期不完整的DataFrame,我只需要每月可用的最后一天的日期/行。 我尝试使用TimeGrouper并获取每个组的.last()

import pandas as pd
idx = [pd.datetime(2016,2,1),pd.datetime(2017,1,20),pd.datetime(2017,2,1),pd.datetime(2017,2,27)]
df = pd.DataFrame([1,2,3,4],index=idx)
df
        0
2016-02-01  1
2017-01-20  2
2017-02-01  3
2017-02-27  4

期待:

df_eom
        0
2016-02-01  1
2017-01-20  2
2017-02-27  4

然而我得到了这个:

df_eom = df.groupby(pd.TimeGrouper(freq='1M')).last()
df_eom
              0
2016-02-29  1.0
2016-03-31  NaN
2016-04-30  NaN
2016-05-31  NaN
2016-06-30  NaN
2016-07-31  NaN
2016-08-31  NaN
2016-09-30  NaN
2016-10-31  NaN
2016-11-30  NaN
2016-12-31  NaN
2017-01-31  2.0
2017-02-28  4.0

不仅创建了不在df中的日期,还改变了df的第一行和最后一行的索引。我使用TimeGrouper错了吗?

3 个答案:

答案 0 :(得分:1)

这是单程

In [795]: df.iloc[df.reset_index().groupby(df.index.to_period('M'))['index'].idxmax()]
Out[795]:
            0
2016-02-01  1
2017-01-20  2
2017-02-27  4

或者

In [802]: df.loc[df.groupby(df.index.to_period('M')).apply(lambda x: x.index.max())]
Out[802]:
            0
2016-02-01  1
2017-01-20  2
2017-02-27  4

答案 1 :(得分:0)

我相信这个解决方案更适合更多用例。以前的实例仅在日期正好是月末时才有效。例如,如果您处理财务数据,则该月的最后一天可能是也可能不是日历月末。此解决方案说明了这一点:

df[df['as_of_date'].dt.month.shift(-1)!=df['as_of_date'].dt.month].reset_index(drop=True)

答案 2 :(得分:-1)

您可以按年份和月份进行分组,并遍历您的群组以查找上次日期。像这样:

groups = df.groupby([df.index.year, df.index.month])
df_eom = pd.DataFrame()
for idx, group in groups:
    df_eom = df_eom.append(group.iloc[-1])
df_eom
            0
2016-02-01  1
2017-01-20  2
2017-02-27  4

由于循环,我不是很喜欢这个,但考虑到你真的不能有多少年,而且每年最多有12个月的小组,所以不应该这样。太可怕了。