Сумма по группам, индекс против столбца - PullRequest
3 голосов
/ 17 мая 2019

Для следующего кадра данных:

df = pd.DataFrame({'group':['a','a','b','b'], 'data':[5,10,100,30]},columns=['group', 'data']) 
print(df)

  group  data
0     a     5
1     a    10
2     b   100
3     b    30

При группировании по столбцу, добавлении и создании нового столбца, получается:

df['new'] = df.groupby('group')['data'].sum() 
print(df)

  group  data  new
0     a     5  NaN
1     a    10  NaN
2     b   100  NaN
3     b    30  NaN

Однако, если мы сбросим df на исходные данные и переместим столбец группы в индекс,

df.set_index('group', inplace=True)
print(df)

       data
group      
a         5
a        10
b       100
b        30

А затем группа и сумма, тогда мы получим:

df['new'] = df.groupby('group')['data'].sum() 
print(df)

       data  new
group           
a         5   15
a        10   15
b       100  130
b        30  130

Почему группа столбцов не устанавливает значения в новом столбце, а группа индексов устанавливает значения в новом столбце?

Ответы [ 2 ]

4 голосов
/ 17 мая 2019

Лучше использовать GroupBy.transform для возвращаемых серий с таким же размером, как у оригинала DataFrame, поэтому после назначения все работает правильно:

df['new'] = df.groupby('group')['data'].transform('sum')

Потому что если назначитьновые значения Серии выровнены по значениям индекса.Если индекс отличается, получить NaN s:

print (df.groupby('group')['data'].sum())
group
a     15
b    130
Name: data, dtype: int64

Различные значения индекса - получить NaN:

print (df.groupby('group')['data'].sum().index)
Index(['a', 'b'], dtype='object', name='group')

print (df.index)
RangeIndex(start=0, stop=4, step=1)

df.set_index('group', inplace=True)

print (df.groupby('group')['data'].sum())
group
a     15
b    130
Name: data, dtype: int64

Индекс можно выровнять, так как значения совпадают:

print (df.groupby('group')['data'].sum().index)
Index(['a', 'b'], dtype='object', name='group')

print (df.index)
Index(['a', 'a', 'b', 'b'], dtype='object', name='group')
2 голосов
/ 17 мая 2019

Вы не получаете то, что хотите, потому что при использовании df.groupby('group')['data'].sum() это возвращает агрегированный результат с group в качестве индекса:

group
a     15
b    130
Name: data, dtype: int64

Где явно не выровнены индексы.

Если вы хотите, чтобы это работало, вам придется использовать transform, который возвращает серию с преобразованными долями, у которых имеет ту же длину оси, что и у себя :

df['new'] = df.groupby('group')['data'].transform('sum')

   group  data  new
0     a     5   15
1     a    10   15
2     b   100  130
3     b    30  130
...