将带有datetime键的pd.Grouper与另一个键结合使用可以创建一组组,但在我看来,这似乎并不包含需要创建的所有组。
>>> test = pd.DataFrame({"id":["a","b"]*3, "b":pd.date_range("2000-01-01","2000-01-03", freq="9H")})
>>> test
id b
0 a 2000-01-01 00:00:00
1 b 2000-01-01 09:00:00
2 a 2000-01-01 18:00:00
3 b 2000-01-02 03:00:00
4 a 2000-01-02 12:00:00
5 b 2000-01-02 21:00:00
当我尝试根据日期和id
值创建组时:
>>> g = test.groupby([pd.Grouper(key='b', freq="D"), 'id'])
>>> g.groups
{(2000-01-01 00:00:00, 'a'): [0], (2000-01-02 00:00:00, 'b'): [1]}
g.groups
只显示了2个组,而我预期为4个组:“a”和“b”代表每一天。
然而,当我基于“b”创建另一列时:
>>> test['date'] = test.b.dt.date
>>> g = test.groupby(['date', 'id'])
>>> g.groups
{(2000-01-01, 'a'): [0, 2], (2000-01-01, 'b'): [1], (2000-01-02, 'a'): [4], (2000-01-02, 'b'): [3, 5]}
结果和我预料的完全一样。
我不知道如何理解这些不同的结果,请你开导我。
2条答案
按热度按时间y4ekin9u1#
您确实有4个组使用
Grouper
,g.groups
的输出具有误导性(可能值得作为bug报告?):1szpjjfi2#
我相信这是因为'pd.Grouper'和pandas中的'dt.date'方法之间的差异。'pd.Grouper'按一系列值(例如,每天、每小时等)分组,而'dt.date'只返回datetime对象的日期部分,有效地创建了一个分类变量。
当您以“D”的频率使用'pd.Grouper'时,它将按完整的天进行分组,因此每天仅由一个组表示。但在您的情况下,每个ID对于给定的天具有多个记录。因此,'pd.Grouper'无法捕获您期望的所有组。
另一方面,当您使用'dt.date'方法提取datetime的日期部分时,它会创建一个独立表示每个日期的分类变量。
因此,当您按照这个新的date列沿着id列进行分组时,每个组将对应于date和id的唯一组合,从而得到预期的结果。
总之,当您希望按一定范围的值(例如,每天、每小时)进行分组时,pd.Grouper非常有用;而当您希望按特定值进行分组时,使用单独的列来存储精确值(例如,仅存储日期的列)非常有用。