2015-02-05 4 views
2

Допустим, я создаю DataFrame:Панды объединить агрегированные столбцов

import pandas as pd 
df = pd.DataFrame({"a": [1,2,3,13,15], "b": [4,5,6,6,6], "c": ["wish", "you","were", "here", "here"]}) 

так:

a b c 
0 1 4 wish 
1 2 5 you 
2 3 6 were 
3 13 6 here 
4 15 6 here 

..., а затем группы и совокупный на пару колонок ...

gb = df.groupby(['b','c']).agg({"a": lambda x: x.nunique()}) 

Получение следующего результата:

  a 
b c 
4 wish 1 
5 you  1 
6 here 2 
    were 1 

Можно ли объединить df с новой агрегированной таблицей gb, чтобы создать новый столбец в df, содержащий соответствующие значения от gb? Как это:

a b c  nc 
0 1 4 wish 1 
1 2 5 you  1 
2 3 6 were 1 
3 13 6 here 2 
4 15 6 here 2 

Я пытался делать простейшую вещь:

df.merge(gb, on=['b','c']) 

Но это дает ошибку:

KeyError: 'b' 

Который имеет смысл, поскольку сгруппированная таблица имеет многоиндексную и b не является столбцом. Так что мой вопрос два раза:

  1. Могу ли я превратить мульти-индекс gb DataFrame обратно в колонны (так, что она имеет столбец b и c)?
  2. Могу ли я объединить df с gb на имена столбцов?

ответ

5

Всякий раз, когда вы хотите добавить агрегированный столбец из операции GroupBy обратно в ДФ вы должны использовать transform, это производит серию с его индексом выровненной с ориг ДФ:

In [4]: 

df['nc'] = df.groupby(['b','c'])['a'].transform(pd.Series.nunique) 
df 
Out[4]: 
    a b  c nc 
0 1 4 wish 1 
1 2 5 you 1 
2 3 6 were 1 
3 13 6 here 2 
4 15 6 here 2 

Нет необходимости сбросить индекс или выполнить дополнительное слияние.

+0

Это великолепно. Гораздо более элегантный, чем мое решение. –

+0

Согласовано - ответ @ aus_lacy отвечает на вопрос OP, но это еще лучший способ сделать это. –

+2

мы можем сделать это на нескольких операциях: count/sum/etc ... с автоматическими новыми столбцами для каждой операции? –

2

Существует простой способ сделать это, используя reset_index().

df.merge(gb.reset_index(), on=['b','c']) 

дает

a_x b c a_y 
0 1 4 wish 1 
1 2 5 you 1 
2 3 6 were 1 
3 13 6 here 2 
4 15 6 here 2 
+0

@ Метод EdChum намного превосходит мой. –

+0

Можно ли поместить результат 'agg' в новый столбец, чтобы слияние не переименовывало столбцы? Преимущество использования 'reset_index', я полагаю, заключается в том, что количество строк в таблице агрегатов соответствует количеству ключей агрегации (т.е. ['b', 'c']), которые я могу сохранить для дальнейшего анализа за слиянием. –

+0

@ можжевельник - вам нужно будет переименовать имена столбцов, которые столкнулись, чтобы слияние не добавляло суффикс. Вы можете сохранить объект groupby как переменную, это всего лишь объект, который описывает, как должна выполняться групповая операция, при этом не выполняются ограничения производительности при выполнении этого – EdChum