Панды: возьмите скользящую сумму следующих (1 ... n) строк столбца в группе и создайте новый столбец для каждой суммы - PullRequest
0 голосов
/ 11 октября 2018

У меня есть следующий фрейм данных:

a = [1,2,3,4,5,6,7,8]
x1 = ['j','j','j','k','k','k','k','k']
df = pd.DataFrame({'a': a,'b':x1})  

print(df)

a   b
1   j
2   j
3   j
4   k
5   k
6   k
7   k
8   k

Я пытаюсь получить сумму значений "a" для следующих n строк, сгруппированных в столбце "b", и сохранить ее в новых столбцах (для n в диапазоне отС 1 по 4).

По сути, я хочу получить четыре новых столбца c1, c2, c3 и c4, в которых c1 имеет сумму «следующих 1» a, c2 имеет сумму «следующих 2» a, c3 имеет сумму«следующие 3» а и с4 имеют сумму «следующих 4» а.

Поэтому мой желаемый результат:

a   b   c1      c2      c3      c4  
1   j   2.0     5.0     NaN     NaN
2   j   3.0     NaN     NaN     NaN
3   j   NaN     NaN     NaN     NaN
4   k   5.0     11.0    18.0    26.0
5   k   6.0     13.0    21.0    NaN
6   k   7.0     15.0    NaN     NaN
7   k   8.0     NaN     NaN     NaN
8   k   NaN     NaN     NaN     NaN

Я искал решения, и лучшее, что я могу придумать, это что-тонапример:

for x in range(1,5): 
    df[x] = df.groupby(['b'])a[::-1].rolling(x+1).sum()[::-1] - a

, но этот синтаксис выдает ошибки.

Если возможно, вы также можете поделиться, как реализовать, если мне нужно сгруппировать по нескольким полям.Буду очень признателен за любую помощь.

Спасибо.

1 Ответ

0 голосов
/ 11 октября 2018

Ваш примерный фрейм данных не соответствует ожидаемому результату, поэтому давайте перейдем к последнему.

Я думаю, вы можете объединить скользящую сумму со сдвигом:

for x in range(1, 5):
    c = pd.Series(df.groupby("b")["a"].rolling(x).sum().values, index=df.index)
    df[f"c{x}"]= c.groupby(df["b"]).shift(-x)

дает мне

In [302]: df
Out[302]: 
   a  b   c1    c2    c3    c4
0  1  j  2.0   5.0   NaN   NaN
1  2  j  3.0   NaN   NaN   NaN
2  3  j  NaN   NaN   NaN   NaN
3  4  k  5.0  11.0  18.0  26.0
4  5  k  6.0  13.0  21.0   NaN
5  6  k  7.0  15.0   NaN   NaN
6  7  k  8.0   NaN   NaN   NaN
7  8  k  NaN   NaN   NaN   NaN

Если вы действительно хотите иметь несколько клавиш, вы можете использовать список клавиш, но нам нужно немного переставить вызов:

keys = ["b","b2"]
for x in range(1, 5):
    c = pd.Series(df.groupby(keys)["a"].rolling(x).sum().values, index=df.index)
    df[f"c{x}"]= c.groupby([df[k] for k in keys]).shift(-x)

или

keys = ["b","b2"]
for x in range(1, 5):
    c = pd.Series(df.groupby(keys)["a"].rolling(x).sum().values, index=df.index)
    df[f"c{x}"]= df.assign(tmp=c).groupby(keys)["tmp"].shift(-x)

дай мне

In [409]: df
Out[409]: 
   a  b b2   c1    c2  c3  c4
0  1  j  j  2.0   5.0 NaN NaN
1  2  j  j  3.0   NaN NaN NaN
2  3  j  j  NaN   NaN NaN NaN
3  4  k  k  5.0   NaN NaN NaN
4  5  k  k  NaN   NaN NaN NaN
5  6  k  l  7.0  15.0 NaN NaN
6  7  k  l  8.0   NaN NaN NaN
7  8  k  l  NaN   NaN NaN NaN
...