wake-up-neo.com

Pandas: Wie wird ein Pivot mit einem Multi-Index ausgeführt?

Ich möchte einen Pivot auf einem pandas DataFrame ausführen, wobei der Index zwei Spalten und nicht eine enthält. Zum Beispiel ein Feld für das Jahr, eines für den Monat, ein 'item'-Feld, das' item 1 'und' item 2 'anzeigt und ein' value'-Feld mit numerischen Werten Ich möchte, dass der Index Jahr + Monat ist.

Die einzige Möglichkeit, dies zum Laufen zu bringen, bestand darin, die beiden Felder zu einem zusammenzufassen und sie dann wieder zu trennen. Gibt es einen besseren Weg?

Minimaler Code unten kopiert. Vielen Dank!

PS Ja, ich bin mir bewusst, dass es andere Fragen mit den Schlüsselwörtern 'Pivot' und 'Multi-Index' gibt, aber ich habe nicht verstanden, ob/wie sie mir bei dieser Frage helfen können.

import pandas as pd
import numpy as np

df= pd.DataFrame()
month = np.arange(1, 13)
values1 = np.random.randint(0, 100, 12)
values2 = np.random.randint(200, 300, 12)


df['month'] = np.hstack((month, month))
df['year'] = 2004
df['value'] = np.hstack((values1, values2))
df['item'] = np.hstack((np.repeat('item 1', 12), np.repeat('item 2', 12)))

# This doesn't work: 
# ValueError: Wrong number of items passed 24, placement implies 2
# mypiv = df.pivot(['year', 'month'], 'item', 'value')

# This doesn't work, either:
# df.set_index(['year', 'month'], inplace=True)
# ValueError: cannot label index with a null key
# mypiv = df.pivot(columns='item', values='value')

# This below works but is not ideal: 
# I have to first concatenate then separate the fields I need
df['new field'] = df['year'] * 100 + df['month']

mypiv = df.pivot('new field', 'item', 'value').reset_index()
mypiv['year'] = mypiv['new field'].apply( lambda x: int(x) / 100)  
mypiv['month'] = mypiv['new field'] % 100
39

Sie können gruppieren und dann entstapeln.

>>> df.groupby(['year', 'month', 'item'])['value'].sum().unstack('item')
item        item 1  item 2
year month                
2004 1          33     250
     2          44     224
     3          41     268
     4          29     232
     5          57     252
     6          61     255
     7          28     254
     8          15     229
     9          29     258
     10         49     207
     11         36     254
     12         23     209

Oder benutze pivot_table:

>>> df.pivot_table(
        values='value', 
        index=['year', 'month'], 
        columns='item', 
        aggfunc=np.sum)
item        item 1  item 2
year month                
2004 1          33     250
     2          44     224
     3          41     268
     4          29     232
     5          57     252
     6          61     255
     7          28     254
     8          15     229
     9          29     258
     10         49     207
     11         36     254
     12         23     209
57
Alexander

Ich glaube, wenn Sie item in Ihren MultiIndex aufnehmen, können Sie einfach das Stapeln aufheben:

df.set_index(['year', 'month', 'item']).unstack(level=-1)

Dies ergibt:

                value      
item       item 1 item 2
year month              
2004 1         21    277
     2         43    244
     3         12    262
     4         80    201
     5         22    287
     6         52    284
     7         90    249
     8         14    229
     9         52    205
     10        76    207
     11        88    259
     12        90    200

Es ist ein bisschen schneller als mit pivot_table und ungefähr genauso schnell oder etwas langsamer als mit groupby.

21
Ajean