pandas groupby语句

时间:2015-10-26 14:43:13

标签: python pandas

我有一个数据框,其中包含不同产品的每周销售额(a,b,c):

In[1]
df = pd.DataFrame({'product': list('aaaabbbbcccc'),
               'week': [1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4],
               'sales': np.power(2, range(12))})
Out[1]
   product  sales  week
0        a      1     1
1        a      2     2
2        a      4     3
3        a      8     4
4        b     16     1
5        b     32     2
6        b     64     3
7        b    128     4
8        c    256     1
9        c    512     2
10       c   1024     3
11       c   2048     4

我想创建一个新列,其中包含过去n周的累计销售额,按产品分组。例如。对于n=2,它应该像last_2_weeks

   product  sales  week  last_2_weeks
0        a      1     1             0
1        a      2     2             1
2        a      4     3             3
3        a      8     4             6
4        b     16     1             0
5        b     32     2            16
6        b     64     3            48
7        b    128     4            96
8        c    256     1             0
9        c    512     2           256
10       c   1024     3           768
11       c   2048     4          1536

如何在熊猫中有效地计算出这种累积的条件总和?如果有更多变量要分组,解决方案也应该有用,例如产品和地点。

我尝试过创建一个新函数并使用groupbyapply,但这仅适用于行的排序。它也很慢而且丑陋。

def last_n_weeks(x):
    """ calculate sales of previous n weeks in aggregated data """
    n = 2
    cur_week = x['week'].iloc[0]
    cur_prod = x['product'].iloc[0]
    res = np.sum(df['sales'].loc[((df['product'] == cur_prod) &
                         (df['week'] >= cur_week-n) & (df['week'] < cur_week))])
    return res

df['last_2_weeks'] = df.groupby(['product', 'week']).apply(last_n_weeks).reset_index(drop=True)

1 个答案:

答案 0 :(得分:2)

您可以将pd.rolling_sumwindow=2一起使用,然后shift使用NaNs,并将0填入In [114]: df['l2'] = (df.groupby('product')['sales'] .apply(lambda x: pd.rolling_sum(x, window=2, min_periods=0) .shift() .fillna(0))) In [115]: df Out[115]: product sales week l2 0 a 1 1 0 1 a 2 2 1 2 a 4 3 3 3 a 8 4 6 4 b 16 1 0 5 b 32 2 16 6 b 64 3 48 7 b 128 4 96 8 c 256 1 0 9 c 512 2 256 10 c 1024 3 768 11 c 2048 4 1536

service.shutdown()
相关问题