2014-08-30 94 views
1

我想计算每个群组每周的最大值,并在熊猫中创建一个包含这些值的新列。我在posted一个类似的问题,没有解决我的问题,所以我重构了这个问题。从日期时间范围和熊猫群体计算的列

考虑使用时间戳,组和值列的数据帧:

datetime  group value 
2014-05-07 A  3 
2014-05-07 B  4 
2014-05-14 A  4 
2014-05-14 B  2 
2014-05-15 A  6 
2014-05-15 B  4 
2014-05-16 A  7 
2014-05-16 B  10 

我想与组每周最大值创建新列:

datetime  group value maxval 
2014-05-07 A  3  3 
2014-05-07 B  4  4 
2014-05-14 A  4  7 
2014-05-14 B  2  10 
2014-05-15 A  6  7 
2014-05-15 B  4  10 
2014-05-16 A  7  7 
2014-05-16 B  10  10 

在链接的问题,所提出的解决方案是转换一个groupby子句,然后将其附加到数据框,但是这会造成系列中的排序错误。

回答

2

您可以transform组索引上都group,同时周:

>>> week = pd.DatetimeIndex(df.datetime).week 
>>> df["maxval"] = df.groupby(['group', week])["value"].transform('max') 
>>> df 
    datetime group value maxval 
0 2014-05-07  A  3  3 
1 2014-05-07  B  4  4 
2 2014-05-14  A  4  7 
3 2014-05-14  B  2  10 
4 2014-05-15  A  6  7 
5 2014-05-15  B  4  10 
6 2014-05-16  A  7  7 
7 2014-05-16  B  10  10 

请注意,如果您有多个年,这将每年的第二周(例如)合并到同组。

有时候人们会这么想,但如果你不这样做,你可以用同样的方法将年份加到分组数量上。


如果你想,而不是滚动最大,你可以使用(恰如其分)rolling_max。您可以重新取样自己或让rolling_max做到这一点,像

def rolling_max_week(x): 
    rolled = pd.rolling_max(x, 7, min_periods=1, center=True, freq='d') 
    match_x = rolled.loc[x.index] 
    return match_x 

df["datetime"] = pd.to_datetime(df["datetime"]) 
df = df.set_index("datetime") 
df["rolling_max"] = df.groupby("group")["value"].transform(rolling_max_week) 
df["bin_max"] = df.groupby(["group", df.index.week])["value"].transform(max) 

现在,因为它发生,这两个产生于你的样品完全相同的输出:

>>> df 
      group value rolling_max bin_max 
datetime          
2014-05-07  A  3   3  3 
2014-05-07  B  4   4  4 
2014-05-14  A  4   7  7 
2014-05-14  B  2   10  10 
2014-05-15  A  6   7  7 
2014-05-15  B  4   10  10 
2014-05-16  A  7   7  7 
2014-05-16  B  10   10  10 

,但不会是一般来说是真的。您需要阅读rolling_max的文档,并尝试使用一些测试用例,以确保我能正确解释您想要的内容。

+0

如果我想从每天中选择一周,该怎么办?例如,将一天当作中间一周,并且在三天之前和三天之后进行? – camdenl 2014-08-30 17:06:14

+0

我不知道我关注。你是否试图(1)将一周的定义改变几天,或者(2)你想要一个滚动窗口,以便每天有不同的一周,我们正在取得最大的结果? – DSM 2014-08-30 17:11:48

+0

一个移动的窗口,每天都有一个不同的星期,以当天为中位数。 – camdenl 2014-08-30 17:16:43