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

cxw*_*xwf 5 python python-datetime pandas datetimeindex pandas-groupby

我有一个日期不完整的 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
Run Code Online (Sandbox Code Playgroud)

期待:

df_eom
        0
2016-02-01  1
2017-01-20  2
2017-02-27  4
Run Code Online (Sandbox Code Playgroud)

但是我得到了这个:

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
Run Code Online (Sandbox Code Playgroud)

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

Zer*_*ero 7

这是一种方法

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
Run Code Online (Sandbox Code Playgroud)

或者

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
Run Code Online (Sandbox Code Playgroud)


Grr*_*Grr 0

您可以按年和月进行分组,并迭代您的组以查找最后一个日期。就像这样:

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
Run Code Online (Sandbox Code Playgroud)

我不太喜欢这个,因为有循环,但考虑到你确实不能有太多的年数,而且每年最多有 12 个月的组,所以应该不会太糟糕。