сводная таблица против groupby: имена столбцов - PullRequest
0 голосов
/ 12 мая 2018

df_tier

device_id   month_id    net_grp     watch_hours class
843         201707      TCH         0.250277    Ser
896         201803      NJV         0.820833    Ser
748         201711      SHX         2.461111    Sr
115         201712      SPE         1.478055    Opter
107         201802      US          2.575555    Opter
249         201710      ECC         3.869166    Ser
786         201711      NCK         0.563888    Opter
183         201802      HO          1.690555    Opter
752         201712      LC          0.993611    Opter

Я делаю операцию поворота для набора данных, конечный результат будет содержать около 5 миллионов строк и 600 столбцов. Выше приведен пример данных, из которых создается сводная таблица.

#Pivot
df_tier.pivot_table(index=['device_id'],
                        columns = 'net_grp',
                        values = 'watch_hours',
                        aggfunc = sum,fill_value = 0).reset_index()

эта операция для выборки из 200000 записей занимает около 93,7 мс, а когда я делаю группировку, как показано ниже:

#Grouby
df_tier.groupby(['device_id','net_grp']).agg({'tuning_hours':['sum']}).unstack(level='net_grp').fillna(0).reset_index().set_index('device_id')

, что занимает около 15 мс.

Однако вывод pivot более удобен, так как содержит правильные имена столбцов, в то время как вывод из groupby:

Неправильные имена столбцов в группе,

( 'watch_hours', 'сумма', 'TCH'), ( 'watch_hours', 'сумма', 'SPE'), ( 'watch_hours', 'сумма', 'NCK')

Как я могу получить только net_grp, скажем, TCH из них как имена столбцов?

Я хочу использовать groupby из-за проблем с производительностью, когда я запускаю все данные Может кто-нибудь помочь мне правильно назвать имена столбцов?

Спасибо

1 Ответ

0 голосов
/ 12 мая 2018

Я предлагаю использовать sum вместо agg, что убирает первый и второй ненужный уровень из Multiindex в столбцах:

df1 = (df_tier.groupby(['device_id','net_grp'])['watch_hours']
              .sum()
              .unstack(level='net_grp', fill_value=0))
print (df1)
net_grp         ECC        HO        LC       NCK       NJV       SHX  \
device_id                                                               
107        0.000000  0.000000  0.000000  0.000000  0.000000  0.000000   
115        0.000000  0.000000  0.000000  0.000000  0.000000  0.000000   
183        0.000000  1.690555  0.000000  0.000000  0.000000  0.000000   
249        3.869166  0.000000  0.000000  0.000000  0.000000  0.000000   
748        0.000000  0.000000  0.000000  0.000000  0.000000  2.461111   
752        0.000000  0.000000  0.993611  0.000000  0.000000  0.000000   
786        0.000000  0.000000  0.000000  0.563888  0.000000  0.000000   
843        0.000000  0.000000  0.000000  0.000000  0.000000  0.000000   
896        0.000000  0.000000  0.000000  0.000000  0.820833  0.000000   

net_grp         SPE       TCH        US  
device_id                                
107        0.000000  0.000000  2.575555  
115        1.478055  0.000000  0.000000  
183        0.000000  0.000000  0.000000  
249        0.000000  0.000000  0.000000  
748        0.000000  0.000000  0.000000  
752        0.000000  0.000000  0.000000  
786        0.000000  0.000000  0.000000  
843        0.000000  0.250277  0.000000  
896        0.000000  0.000000  0.000000 

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

df1 = (df_tier.groupby(['device_id','net_grp'])
              .agg({'watch_hours':['sum']})
              .unstack(level='net_grp', fill_value=0))

df1.columns = df1.columns.droplevel([0,1])
...