Возврат агрегированного кадра данных из pandas groupby
Я пытаюсь обернуть голову вокруг методов Pandas groupby. Я хотел бы написать функцию, которая выполняет некоторые функции агрегации, а затем возвращает Pandas DataFrame. Здесь представлен упрощенный пример с использованием sum(). Я знаю, что есть простые способы делать простые суммы, в реальной жизни моя функция сложнее:
import pandas as pd
df = pd.DataFrame({'col1': ['A', 'A', 'B', 'B'], 'col2':[1.0, 2, 3, 4]})
In [3]: df
Out[3]:
col1 col2
0 A 1
1 A 2
2 B 3
3 B 4
def func2(df):
dfout = pd.DataFrame({ 'col1' : df['col1'].unique() ,
'someData': sum(df['col2']) })
return dfout
t = df.groupby('col1').apply(func2)
In [6]: t
Out[6]:
col1 someData
col1
A 0 A 3
B 0 B 7
Я не ожидал, что там будет col1
, и я не ожидал, что этот тайный индекс будет выглядеть. Я действительно думал, что просто получаю col1
и someData
.
В моем приложении для реальной жизни я группирую более одного столбца и действительно хотел бы вернуть DataFrame, а не объект Series.
Любые идеи для решения или объяснения того, что делает Pandas в моем примере выше?
----- добавлена информация -----
Я должен был начать с этого примера, я думаю:
In [13]: import pandas as pd
In [14]: df = pd.DataFrame({'col1':['A','A','A','B','B','B'], 'col2':['C','D','D','D','C','C'], 'col3':[.1,.2,.4,.6,.8,1]})
In [15]: df
Out[15]:
col1 col2 col3
0 A C 0.1
1 A D 0.2
2 A D 0.4
3 B D 0.6
4 B C 0.8
5 B C 1.0
In [16]: def func3(df):
....: dfout = sum(df['col3']**2)
....: return dfout
....:
In [17]: t = df.groupby(['col1', 'col2']).apply(func3)
In [18]: t
Out[18]:
col1 col2
A C 0.01
D 0.20
B C 1.64
D 0.36
В приведенной выше иллюстрации результатом функции apply()
является серия Pandas. И ему не хватает столбцов groupby из df.groupby
. Суть того, с чем я борюсь, - это как создать функцию, которую я применяю к группе, которая возвращает как результат функции AND, так и столбцы, на которых она была сгруппирована?
----- еще одно обновление ------
Похоже, что если я сделаю это:
pd.DataFrame(t).reset_index()
Я возвращаю DataFrame, который действительно близок к тому, что я был после.
Ответы
Ответ 1
Причина, по которой вы видите столбцы с 0, состоит в том, что вывод .unique()
представляет собой массив .
Лучший способ понять, как будет работать ваш прием, - проверить каждую группу действий:
In [11] :g = df.groupby('col1')
In [12]: g.get_group('A')
Out[12]:
col1 col2
0 A 1
1 A 2
In [13]: g.get_group('A')['col1'].unique()
Out[13]: array([A], dtype=object)
In [14]: sum(g.get_group('A')['col2'])
Out[14]: 3.0
В большинстве случаев вы хотите, чтобы это было агрегированное значение .
Вывод grouped.apply
всегда будет иметь метки группы как индекс (уникальные значения "col1" ), поэтому ваша примерная конструкция col1
кажется мне немного тупой.
Примечание. Чтобы поместить 'col1'
(индекс) обратно в столбец, вы можете вызвать reset_index
, поэтому в этом случае.
In [15]: g.sum().reset_index()
Out[15]:
col1 col2
0 A 3
1 B 7