Подтвердить что ты не робот

Python - функции качения для объекта GroupBy

У меня есть объект временного ряда grouped типа <pandas.core.groupby.SeriesGroupBy object at 0x03F1A9F0>. grouped.sum() дает желаемый результат, но я не могу заставить rol_sum работать с объектом groupby. Есть ли способ применить функции качения к объектам groupby? Например:

x = range(0, 6)
id = ['a', 'a', 'a', 'b', 'b', 'b']
df = DataFrame(zip(id, x), columns = ['id', 'x'])
df.groupby('id').sum()
id    x
a    3
b   12

Однако я хотел бы иметь что-то вроде:

  id  x
0  a  0
1  a  1
2  a  3
3  b  3
4  b  7
5  b  12
4b9b3361

Ответ 1

Примечание: как определено @kekert, следующий шаблон панд устарел. Смотрите текущие решения в ответах ниже.

In [16]: df.groupby('id')['x'].apply(pd.rolling_mean, 2, min_periods=1)
Out[16]: 
0    0.0
1    0.5
2    1.5
3    3.0
4    3.5
5    4.5

In [17]: df.groupby('id')['x'].cumsum()
Out[17]: 
0     0
1     1
2     3
3     3
4     7
5    12

Ответ 2

Для гуглеров, которые приходят на этот старый вопрос:

Относительно комментария @kekert на ответ @Garrett для использования нового

df.groupby('id')['x'].rolling(2).mean()

а не устаревший

df.groupby('id')['x'].apply(pd.rolling_mean, 2, min_periods=1)

Любопытно, что новый подход .rolling(). mean() возвращает многоиндексированную серию, сначала индексированную столбцом group_by, а затем индекс. Принимая во внимание, что старый подход просто вернул бы серию, индексированную исключительно исходным индексом df, что, возможно, имеет меньшее значение, но очень удобно для добавления этой серии в новый столбец в исходный фрейм.

Итак, я думаю, что я нашел решение, которое использует новый метод roll() и по-прежнему работает одинаково:

df.groupby('id')['x'].rolling(2).mean().reset_index(0,drop=True)

который должен дать вам серию

0    0.0
1    0.5
2    1.5
3    3.0
4    3.5
5    4.5

который вы можете добавить в качестве столбца:

df['x'] = df.groupby('id')['x'].rolling(2).mean().reset_index(0,drop=True)

Ответ 3

Вот еще один способ, который хорошо обобщает и использует метод расширения панд.

Это очень эффективно, а также отлично подходит для расчета скользящих окон с фиксированными окнами, например, для временных рядов.

# Import pandas library
import pandas as pd

# Prepare columns
x = range(0, 6)
id = ['a', 'a', 'a', 'b', 'b', 'b']

# Create dataframe from columns above
df = pd.DataFrame({'id':id, 'x':x})

# Calculate rolling sum with infinite window size (i.e. all rows in group) using "expanding"
df['rolling_sum'] = df.groupby('id')['x'].transform(lambda x: x.expanding().sum())

# Output as desired by original poster
print(df)
  id  x  rolling_sum
0  a  0            0
1  a  1            1
2  a  2            3
3  b  3            3
4  b  4            7
5  b  5           12

Ответ 4

Я не уверен в механике, но это работает. Обратите внимание, что возвращаемое значение - это просто ndarray. Я думаю, вы могли бы применить любую кумулятивную или "скользящую" функцию таким образом, и она должна иметь тот же результат.

Я тестировал его с помощью cumprod, cummax и cummin, и все они вернули ndarray. Я думаю, что pandas достаточно умен, чтобы знать, что эти функции возвращают серию, и поэтому функция применяется как преобразование, а не агрегация.

In [35]: df.groupby('id')['x'].cumsum()
Out[35]:
0     0
1     1
2     3
3     3
4     7
5    12

Изменить: мне было любопытно, что этот синтаксис возвращает строку:

In [54]: df.groupby('id')['x'].transform('cumsum')
Out[54]:
0     0
1     1
2     3
3     3
4     7
5    12
Name: x