Ich habe ein MultiIndex pandas DataFrame nach dem Aufruf groupby
, und müssen es in einer Art und Weise glätten similar to flattening a pivot table. Der Großteil der Analyse ist bereits um das gruppierte Objekt herum aufgebaut und würde daher nicht in eine Pivot-Tabelle umgeformt werden müssen.Flachen Pandas DataFrame ohne Pivot-Tabelle
Betrachten wir einige Blinddaten,
dummy_data = pd.DataFrame({'Ccy' : ['EUR', 'EUR', 'CAD', 'CAD', 'EUR', 'EUR', 'CAD', 'EUR'],
'Venue' : ['BAML']*5 + ['BARX']*3,
'Price': np.abs(np.random.randn(8)),
'volume': np.abs(10*np.random.randn(8))
},
index = pd.date_range('7/19/2017', periods=8))
dummy_data.index.name = "datetime"
print dummy_data
>>> Ccy Price Venue volume
datetime
2017-07-19 EUR 1.338521 BAML 11.227553
2017-07-20 EUR 0.882715 BAML 0.307711
2017-07-21 CAD 0.977815 BAML 14.196170
2017-07-22 CAD 1.262272 BAML 0.055213
2017-07-23 EUR 0.752433 BAML 5.315777
2017-07-24 EUR 0.699008 BARX 2.299045
2017-07-25 CAD 1.625567 BARX 6.474822
2017-07-26 EUR 2.122562 BARX 5.026135
Ziel zu Gruppendaten von Ccy
und Venue
, gelten ein filter
Betrieb jeder Untergruppe, und dann die Gruppen in das Format dieses ursprünglichen Rahmen abzuflachen zurück. Betrachten wir einen einfachen Filter, Zeilen behält wo price > 0.8
dummy_data.groupby(['Ccy', 'Venue']).apply(lambda x: x[x['Price'] > 0.8])
>>> Ccy Price Venue volume
Ccy Venue datetime
CAD BAML 2017-07-21 CAD 0.977815 BAML 14.196170
2017-07-22 CAD 1.262272 BAML 0.055213
BARX 2017-07-25 CAD 1.625567 BARX 6.474822
EUR BAML 2017-07-19 EUR 1.338521 BAML 11.227553
2017-07-20 EUR 0.882715 BAML 0.307711
BARX 2017-07-26 EUR 2.122562 BARX 5.026135
Alles, was ich jetzt brauchen, ist zu fill-in/abflachen die Ccy
und Venue
Spalten, so dass
Ccy Venue datetime
CAD BAML 2017-07-21 ... CAD BAML 2017-07-21 ...
2017-07-22 ... CAD BAML 2017-07-22 ...
BARX 2017-07-25 ... ---> BECOMES ---> CAD BARX 2017-07-25 ...
EUR BAML 2017-07-19 ... EUR BAML 2017-07-19 ...
2017-07-20 ... EUR BAML 2017-07-20 ...
Ich muss dies tun, weil wir haben eine Reihe von Zeichenprogrammen, die nicht flexibel genug sind, um gruppierte Daten zu verarbeiten. Sollte es keine ungroup()
oder flatten()
Methode geben, die reziprok zu der groupby()
Operation ist?
Hinweis: der triviale Filter in diesem Beispiel hätte auf die nicht gruppierten Daten angewendet werden können. In Wirklichkeit ist mein Filter komplexer und macht nur bei Untergruppen Sinn.
Lösungsversuche (Versuche 1 und 2 von pivot table solution)
Attempt 1: melt
Verfahren verliert den datetime
Index.
print dummy_data.groupby(['Ccy', 'Venue']).apply(lambda x: x[x['Price'] > 0.8]).melt()
>>> variable value
0 Ccy CAD
1 Ccy CAD
2 Ccy CAD
3 Ccy EUR
4 Ccy EUR
5 Ccy EUR
6 Price 0.977815
7 Price 1.26227
8 Price 1.62557
9 Price 1.33852
Versuch 2: die accepted answer führt zu einer KeyError
dummy_data.groupby(['Ccy', 'Venue']).apply(lambda x: x[x['Price'] > 0.8]).unstack().reset_index().drop('level_0', axis=1)
KeyError: 'level_0'
Versuch 3:reset_index()
führt zu Valueerror
dummy_data.groupby(['Ccy', 'Venue']).apply(lambda x: x[x['Price'] > 0.8]).reset_index()
ValueError: cannot insert Venue, already exists
Versuch 4:as_index=False
(ohne group_keys
Stichwort)
out = dummy_data.groupby(['Ccy', 'Venue'], as_index=False).apply(lambda x: x[x['Price'] > 0.8])
print out
print out.index
Ccy Price Venue volume
datetime
0 2017-07-21 CAD 0.977815 BAML 14.196170
2017-07-22 CAD 1.262272 BAML 0.055213
1 2017-07-25 CAD 1.625567 BARX 6.474822
2 2017-07-19 EUR 1.338521 BAML 11.227553
2017-07-20 EUR 0.882715 BAML 0.307711
3 2017-07-26 EUR 2.122562 BARX 5.026135
MultiIndex(levels=[[0, 1, 2, 3], [2017-07-19 00:00:00, 2017-07-20 00:00:00, 2017-07-21 00:00:00, 2017-07-22 00:00:00, 2017-07-25 00:00:00, 2017-07-26 00:00:00]],
labels=[[0, 0, 1, 2, 2, 3], [2, 3, 4, 0, 1, 5]],
names=[None, u'datetime'])
Das bekommt mir sehr nahe, aber das Objekt ist immer noch MultiIndexed
. Wie können wir nur den Datetime-Index zurückbekommen?
Ich glaube, Sie reset_index nach Pivot – piRSquared
Check out Versuch 3 in meine Frage aktualisiert –