5

我有一个日期不完整的 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 错了吗?

4

3 回答 3

9

这是一种方法

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
于 2018-02-22T05:20:27.427 回答
0

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

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

于 2021-04-19T19:27:23.213 回答
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

由于循环,我真的不喜欢这个,但考虑到你真的不能有一个离谱的年数,而且每年最多有 12 个月的组,它不应该太糟糕。

于 2018-01-16T19:24:02.317 回答