跨子集的滚动总和

Rolling sum across subsets

我有一个数据集,其中包含每个季度感兴趣的值 ('ee'),以及多个字段,这些字段表示人口的各个子集中的 ee 数量,如下所示:

test=pd.DataFrame(data={'cyq':['2018Q1']*3+['2018Q2']*3+['2018Q3']*3+['2018Q4']*3,
                   'species':['canine','canine','feline']*4,
                   'group':['a','b','a']*4,
                    'ee':range(12)})

我正在尝试获得 ee 在各个季度的滚动总和,具体到其他领域的每个独特子集,在这种情况下是物种和群体。在我的实际数据集中,我总共有六个标识字段。

以下:

test.groupby(['cyq','species','group']).ee.rolling(window=2).sum()

正在生成所有 NaN。我发现的其他解决方案最终会在每个季度内或仅在一个标识字段上滚动总和。我的目标是采用滚动总和,将犬 a、犬 b 和猫 a 识别为不同的,并按季度滚动它们的 ee 值:

非常感谢您的帮助。我觉得有一个简单的解决方案,但我在这里发现的这个问题的变体不适用于我的数据集。

编辑:我拼凑了以下解决方案,但肯定这不是实现目标的最有效或最有效的方法:

test=pd.DataFrame(data={'cyq':['2018Q1']*3+['2018Q2']*3+['2018Q3']*3+['2018Q4']*3,
                   'species':['canine','canine','feline']*4,
                   'group':['a','b','a']*4,
                    'ee':range(12)})
test['cyq']=test.cyq.apply(lambda x: pd.to_datetime(x))
test=test.groupby(['group','species','cyq']).sum().reset_index(level=2)
test=test.groupby(level=[i for i in range(test.index.nlevels)]).rolling('100D',min_periods=2,on='cyq').sum()
test.droplevel([i for i in range(int(test.index.nlevels/2))]).reset_index()

我不认为你从你的第一个代码中得到任何东西,因为没有任何东西会基于那个分组返回。但是,通过删除分组,我能够非常接近您要查找的内容。

test=pd.DataFrame(data={'cyq':['2018Q1']*3+['2018Q2']*3+['2018Q3']*3+['2018Q4']*3,
                   'species':['canine','canine','feline']*4,
                   'group':['a','b','a']*4,
                    'ee':range(12)})
test['ee'] = test['ee'].rolling(window = 2).sum()
test

EDIT2 同样,关于评论,这里有一个可能的解决方案吗?请在您的真实数据上尝试并验证它。

test['cyq']= pd.to_datetime(test['cyq'])
test=test.set_index('cyq').groupby(['species','group']).rolling('100D',min_periods=2).sum()

编辑 根据您对其他答案的评论,我想我知道您在寻找什么。 错误是你在你的 groupby 中包含了你实际上不想包含的宿舍。

test=pd.DataFrame(data={'cyq':['2018Q1']*3+['2018Q2']*3+['2018Q3']*3+['2018Q4']*3,
                   'species':['canine','canine','feline']*4,
                   'group':['a','b','a']*4,
                    'ee':range(12)})

res = test.groupby(['species', 'group'], as_index = False)['ee'].rolling(window=2).sum().join(test['cyq'])
print(res)

   species group    ee     cyq
0   canine     a   NaN  2018Q1
3   canine     a   3.0  2018Q2
6   canine     a   9.0  2018Q3
9   canine     a  15.0  2018Q4
1   canine     b   NaN  2018Q1
4   canine     b   5.0  2018Q2
7   canine     b  11.0  2018Q3
10  canine     b  17.0  2018Q4
2   feline     a   NaN  2018Q1
5   feline     a   7.0  2018Q2
8   feline     a  13.0  2018Q3
11  feline     a  19.0  2018Q4


您没有得到任何结果,因为在您提供的示例中 groupby 每组正好是 1 行。您的滚动 window 是 2。查看 pd.rollingdocumentation,引自 min_periods.

min_periods : int, default None

Minimum number of observations in window required to have a value; otherwise, result is np.nan. For a window that is specified by an integer, min_periods will default to the size of the window.

因为您从来没有 window 两个全值 return NaN。如果您的真实数据更大并且每个组具有更多值,那么您的代码将起作用。 您可以将 min_periods 设置为 1,这样如果至少有一个值,您将得到一个 return 值。