Python 按月分组

Python 按月分组,python,datetime,pandas,Python,Datetime,Pandas,假设我有一个pd.DataFrame,其中索引由pd.DateTimeIndex给出 现在我想每月分组一对,即获得所有的一对。也就是说,我希望有一个组(日期在(一月,二月)),然后(日期在(二月,三月)),等等。自然的方法应该是pd.TimeGrouper,但我找不到一种方法来实现这一点 下面是一个示例数据集请注意,每月观察一次以上(数字随时间变化),因此pd.rolling()和pd.rolling\u apply()似乎不是有效的替代方案: year month

假设我有一个
pd.DataFrame
,其中索引由
pd.DateTimeIndex
给出

现在我想每月分组一对,即获得所有的一对。也就是说,我希望有一个组(
日期在(一月,二月)
),然后(
日期在(二月,三月)
),等等。自然的方法应该是
pd.TimeGrouper
,但我找不到一种方法来实现这一点

下面是一个示例数据集请注意,每月观察一次以上(数字随时间变化),因此
pd.rolling()
pd.rolling\u apply()
似乎不是有效的替代方案:

            year  month          cpsidp
date                                   
2000-01-01  2000      1  19981003169301
2000-02-01  2000      2  20000200000101
2000-02-01  2000      2  20000200000102
2000-02-01  2000      2  20000200000103
2000-02-01  2000      2  20000200000104
2000-02-01  2000      2  20000200000105
2000-03-01  2000      3  19981203124802
2000-04-01  2000      4  20000400000101
2000-05-01  2000      5  19990200854301
2000-06-01  2000      6  19990300018604
2000-07-01  2000      7  20000400000101
2000-08-01  2000      8  19990502683801
2000-09-01  2000      9  19990600006901
2000-10-01  2000     10  19990700006501
2000-11-01  2000     11  19990800083001
2000-12-01  2000     12  19991100000301
2001-01-01  2001      1  19991100000301
2001-02-01  2001      2  19991100002701
2001-03-01  2001      3  20000205949101
2001-04-01  2001      4  20010100107701
2001-05-01  2001      5  20000204516501
2001-06-01  2001      6  20000300112801
2001-07-01  2001      7  20000400000101
2001-08-01  2001      8  20000505217801
以下是我将如何以一种非常不寻常的方式创建这些组:

    dates = df.index.unique()
    for i, date in enumerate(dates):
        if i == len(dates) - 1:
            # last group: no next-group, break
            break
        date1, date2 = date, dates[i+1]
        group = pd.concat((df.loc[date1], df.loc[date2]), axis=0)
        print(group)
试试这个:

In [171]: (df.assign(m1=df.index.year*10**2+df.index.month, m2=df.index.year*10**2+df.index.month+1)
     ...:    .groupby(['m1', 'm2'])
     ...:    .agg({'month':['min','max','size']})
     ...: )
     ...:
Out[171]:
              month
                min max size
m1     m2
200001 200002     1   1    1
200002 200003     2   2    5
200003 200004     3   3    1
200004 200005     4   4    1
200005 200006     5   5    1
200006 200007     6   6    1
200007 200008     7   7    1
200008 200009     8   8    1
200009 200010     9   9    1
200010 200011    10  10    1
200011 200012    11  11    1
200012 200013    12  12    1
200101 200102     1   1    1
200102 200103     2   2    1
200103 200104     3   3    1
200104 200105     4   4    1
200105 200106     5   5    1
200106 200107     6   6    1
200107 200108     7   7    1
200108 200109     8   8    1

不幸的是,
滚动('2M')
不起作用。无论如何,您不能使用
rolling(2)
的主要原因是您每月有一次以上的观察。根据每个月对的汇总方式,您可以先每月汇总一次(每月给自己一次观察),然后使用
rolling(2)


这非常适用于诸如
'max'
'min'
'sum'
'count'
'size'
'first'
'last'


“平均值”
“标准值”
。。。等会特别小心。比如,你必须自己使用
'sum'
'count'
并计算
'mean'
std'
,但这是可以做到的。

所以像
df.groupby(pd.TimeGrouper(frequer='2M')).mean()
不是你需要的吗?@MaxU不,因为这给了我
(一月、二月)
(三月、四月)
-与
(1月,2月)
(2月,3月)
(3月,4月)
相反,您能发布一个小样本数据集,特别是所需的数据集吗?对不起,我应该更清楚一些。每个月可能有多个观察。如果每个月有多个观察,则此方法不起作用。@FooBar,我已更新了我的答案-这就是您需要的吗?我不确定-在缺少的几个月里它将如何工作…我可以将此与滚动应用程序叠加吗?@FooBar yes。如果你提供更多的细节,我们可以直接回答你的问题。现在,我们在跳舞,试着猜你在找什么。您希望最终输出是什么样子的?如果你有答案,编辑你的问题以反映它。这是一个有趣的想法!我想为每个组做一些复杂的事情,因此我在问题中提出一个方法来对数据进行分组,s.t。然后我可以对分组应用我想要的任何函数,然后@MaxU的答案更合适。
df.groupby(pd.TimeGrouper('M')).first().rolling(2).mean()