【问题标题】:Pandas rolling sum with unevenly spaced index具有不均匀索引的 Pandas 滚动总和
【发布时间】:2015-10-28 11:46:39
【问题描述】:

我有一个数据框,其中包含不同产品(a、b、c)的每周销售额。如果某一周(例如第 4 周)的销售额为零,则该周没有记录:

In[1]
df = pd.DataFrame({'product': list('aaaabbbbcccc'),
               'week': [1, 2, 3, 5, 1, 2, 3, 5, 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     5
4        b     16     1
5        b     32     2
6        b     64     3
7        b    128     5
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     5             4
4        b     16     1             0
5        b     32     2            16
6        b     64     3            48
7        b    128     5            64
8        c    256     1             0
9        c    512     2           256
10       c   1024     3           768
11       c   2048     4          1536

如果每周都有记录,我可以使用rolling_sum,如question 中所述。

有没有办法将“周”设置为索引并仅计算该索引的总和?或者我可以重新采样“week”并将所有缺失行的销售额设置为零吗?

【问题讨论】:

  • 澄清一下,您想要滚动总和吗?例如,产品 c 在第 2 周的 last_2_weeks 销售额为 256,这只是第 1 周的值。

标签: python pandas


【解决方案1】:

重采样仅对DatetimeIndexTimedeltaIndexPeriodIndex 有效。
但是reindex 可以使用整数。

首先将列week 设置为索引。然后 df 按列product 分组,并通过每个组的索引的最大值应用重新索引。缺失值由0 填充。

import pandas as pd
import numpy as np

df = pd.DataFrame({'product': list('aaaabbbbcccc'),
               'week': [1, 2, 3, 5, 1, 2, 3, 5, 1, 2, 3, 4],
               'sales': np.power(2, range(12))})

df = df.set_index('week')   

def reindex_by_max_index_of_group(df):
    index = range(1, max(df.index) + 1)
    return df.reindex(index, fill_value=0)

df = df.groupby('product').apply(reindex_by_max_index_of_group)

df.drop(['product'], inplace=True, axis=1)
print df.reset_index()

#   product  week  sales
#0        a     1      1
#1        a     2      2
#2        a     3      4
#3        a     4      0
#4        a     5      8
#5        b     1     16
#6        b     2     32
#7        b     3     64
#8        b     4      0
#9        b     5    128
#10       c     1    256
#11       c     2    512
#12       c     3   1024
#13       c     4   2048

【讨论】:

  • 不错!而不是df.renamedel 我使用类似df.drop(['product'], inplace=True, axis=1)
【解决方案2】:

您可以使用pivot 创建一个自动填充缺失值的表。如果您的原始数据中每周至少有一个条目,则此方法有效,reindex 可用于确保表中每周都有一行。

然后可以将rolling_sum 应用到它:

import pandas, numpy
df = pandas.DataFrame({'product': list('aaaabbbbcccc'),
              'week': [1, 2, 3, 5, 1, 2, 3, 5, 1, 2, 3, 4],
               'sales': numpy.power(2, range(12))})
sales = df.pivot(index='week', columns='product')
# Cope with weeks when there were no sales at all
sales = sales.reindex(range(min(sales.index), 1+max(sales.index))).fillna(0)
# Calculate the sum for the preceding two weeks
pandas.rolling_sum(sales, 3, min_periods=1)-sales

这给出了以下结果,看起来与预期相符(因为它提供了前两周的总和):

product     a   b     c
week                   
1           0   0     0
2           1  16   256
3           3  48   768
4           6  96  1536
5           4  64  3072

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-09
    • 1970-01-01
    • 2017-06-02
    • 2016-12-20
    • 2017-06-19
    • 2020-10-23
    • 2013-01-15
    • 2018-08-16
    相关资源
    最近更新 更多