Ich habe einen Datenrahmen mit einem hierarchischen Index in Achse 1 (Spalten) (aus einer groupby.agg
Operation):
USAF WBAN year month day s_PC s_CL s_CD s_CNT tempf
sum sum sum sum amax amin
0 702730 26451 1993 1 1 1 0 12 13 30.92 24.98
1 702730 26451 1993 1 2 0 0 13 13 32.00 24.98
2 702730 26451 1993 1 3 1 10 2 13 23.00 6.98
3 702730 26451 1993 1 4 1 0 12 13 10.04 3.92
4 702730 26451 1993 1 5 3 0 10 13 19.94 10.94
Ich möchte es reduzieren, damit es so aussieht (Namen sind nicht kritisch - ich könnte sie umbenennen):
USAF WBAN year month day s_PC s_CL s_CD s_CNT tempf_amax tmpf_amin
0 702730 26451 1993 1 1 1 0 12 13 30.92 24.98
1 702730 26451 1993 1 2 0 0 13 13 32.00 24.98
2 702730 26451 1993 1 3 1 10 2 13 23.00 6.98
3 702730 26451 1993 1 4 1 0 12 13 10.04 3.92
4 702730 26451 1993 1 5 3 0 10 13 19.94 10.94
Wie mache ich das? (Ich habe viel versucht, ohne Erfolg.)
Laut einem Vorschlag ist hier der Kopf in diktierter Form
{('USAF', ''): {0: '702730',
1: '702730',
2: '702730',
3: '702730',
4: '702730'},
('WBAN', ''): {0: '26451', 1: '26451', 2: '26451', 3: '26451', 4: '26451'},
('day', ''): {0: 1, 1: 2, 2: 3, 3: 4, 4: 5},
('month', ''): {0: 1, 1: 1, 2: 1, 3: 1, 4: 1},
('s_CD', 'sum'): {0: 12.0, 1: 13.0, 2: 2.0, 3: 12.0, 4: 10.0},
('s_CL', 'sum'): {0: 0.0, 1: 0.0, 2: 10.0, 3: 0.0, 4: 0.0},
('s_CNT', 'sum'): {0: 13.0, 1: 13.0, 2: 13.0, 3: 13.0, 4: 13.0},
('s_PC', 'sum'): {0: 1.0, 1: 0.0, 2: 1.0, 3: 1.0, 4: 3.0},
('tempf', 'amax'): {0: 30.920000000000002,
1: 32.0,
2: 23.0,
3: 10.039999999999999,
4: 19.939999999999998},
('tempf', 'amin'): {0: 24.98,
1: 24.98,
2: 6.9799999999999969,
3: 3.9199999999999982,
4: 10.940000000000001},
('year', ''): {0: 1993, 1: 1993, 2: 1993, 3: 1993, 4: 1993}}
df[:5].to_dict()
als Beispiel hinzufügen, damit andere sie in Ihrem Datensatz lesen können?pandas
Issue-Tracker , eine spezielle Methode dafür zu implementieren.dat.columns = dat.columns.to_flat_index()
. Eingebaute Pandas-Funktion.Antworten:
Ich denke, der einfachste Weg, dies zu tun, wäre, die Spalten auf die oberste Ebene zu setzen:
Hinweis: Wenn die to-Ebene einen Namen hat, können Sie auch über diesen Namen anstatt über 0 darauf zugreifen.
.
Wenn Sie /
join
Ihren MultiIndex in einem Index kombinieren möchten (vorausgesetzt, Sie haben nur Zeichenfolgeneinträge in Ihren Spalten), können Sie:Hinweis: Wir müssen
strip
das Leerzeichen verwenden, wenn es keinen zweiten Index gibt.quelle
['_'.join(col).rstrip('_') for col in df.columns.values]
sum s_CD
anstelle von verwenden möchtens_CD sum
, kann man tundf.columns = ['_'.join(col).rstrip('_') for col in [c[::-1] for c in df.columns.values]]
.quelle
pd.DataFrame(df.to_records(), columns=df.index.names + list(df.columns))
pd.DataFrame(df_volume.to_records(), index=df_volume.index).drop('index', axis=1)
Alle aktuellen Antworten in diesem Thread müssen etwas veraltet sein. Ab
pandas
Version 0.24.0.to_flat_index()
macht das, was Sie brauchen.Aus Pandas eigener Dokumentation :
Ein einfaches Beispiel aus der Dokumentation:
Bewerbung
to_flat_index()
:Verwenden Sie diese Option, um vorhandene
pandas
Spalten zu ersetzenEin Beispiel für die Verwendung
dat
, bei dem es sich um einen DataFrame mit einerMultiIndex
Spalte handelt:quelle
Die Antwort von Andy Hayden ist sicherlich der einfachste Weg - wenn Sie doppelte Spaltenbeschriftungen vermeiden möchten, müssen Sie einige Anpassungen vornehmen
quelle
quelle
Wenn Sie die Aggregationsinformationen aus der zweiten Ebene des Multiindex beibehalten möchten, können Sie Folgendes versuchen:
quelle
new_cols
ist nicht definiert.Der pythonischste Weg, dies zu tun, um die
map
Funktion zu nutzen .Ausgabe
print(df.columns)
:Update mit Python 3.6+ mit f string:
Ausgabe:
quelle
Die einfachste und intuitivste Lösung für mich war, die Spaltennamen mit get_level_values zu kombinieren . Dies verhindert doppelte Spaltennamen, wenn Sie mehr als eine Aggregation in derselben Spalte durchführen:
Wenn Sie ein Trennzeichen zwischen Spalten wünschen, können Sie dies tun. Dies gibt dasselbe zurück wie Seiji Armstrongs Kommentar zur akzeptierten Antwort, der nur Unterstriche für Spalten mit Werten in beiden Indexstufen enthält:
Ich weiß, dass dies dasselbe tut wie Andy Haydens großartige Antwort oben, aber ich denke, dass es auf diese Weise etwas intuitiver und leichter zu merken ist (ich muss mich also nicht weiter auf diesen Thread beziehen), insbesondere für Anfänger von Pandas .
Diese Methode ist auch erweiterbarer, wenn Sie möglicherweise 3 Spaltenebenen haben.
quelle
Nachdem ich alle Antworten durchgelesen hatte, kam ich auf Folgendes:
Verwendungszweck:
Gegeben ein Datenrahmen:
Einzelaggregationsmethode : resultierende Variablen mit dem gleichen Namen wie source :
df.groupby(by="grouper",
as_index = False)
oder.agg(...)
.reset_index ()Einzelne Quellvariable, mehrere Aggregationen : resultierende Variablen, benannt nach Statistiken :
a = df.groupby(..).agg(..); a.columns = a.columns.droplevel(0); a.reset_index()
.Mehrere Variablen, mehrere Aggregationen : resultierende Variablen mit dem Namen (varname) _ (statname) :
a.columns = ["_".join(filter(None, map(str, levels))) for levels in a.columns.values]
unter der Haube (da diese Form deragg()
Ergebnisse inMultiIndex
den Spalten).my_flatten_cols
Helfer nicht haben , ist es möglicherweise einfacher, die von @Seigi : vorgeschlagene Lösung einzugeben. Diesa.columns = ["_".join(t).rstrip("_") for t in a.columns.values]
funktioniert in diesem Fall ähnlich (schlägt jedoch fehl, wenn Sie numerische Beschriftungen in Spalten haben).a.columns = ["_".join(tuple(map(str, t))).rstrip("_") for t in a.columns.values]
) vorgeschlagene Lösung verwenden , aber ich verstehe nicht, warum dertuple()
Aufruf erforderlich ist, und ich glaube, dass diesrstrip()
nur erforderlich ist, wenn einige Spalten einen Deskriptor wie("colname", "")
( was passieren kann, wenn Siereset_index()
vor dem Versuch zu reparieren.columns
)Sie wollen manuell die resultierenden Variablen nennen: (dies ist seit Pandas 0.20.0 veraltet mit keiner adäquaten Alternative als 0,23 )
res.columns = ['A_sum', 'B_sum', 'count']
oder.join()
mehreregroupby
Anweisungen.Fälle, die von der Hilfsfunktion behandelt werden
map(str, ..)
filter(None, ..)
columns.values
die Namen (str
nicht Tupel) zurück..agg()
Sie möglicherweise die unterste Beschriftung für eine Spalte beibehalten oder mehrere Beschriftungen verkettenreset_index()
in der Lage sein, auf normale Weise mit den Gruppenspalten zu arbeiten, also macht es das standardmäßigquelle
tuple()
wissen möchten, warum dies erforderlich ist, können Sie den Beitrag von jxstanford kommentieren. Andernfalls kann es hilfreich sein, die.columns.values
im angegebenen Beispiel zu überprüfen :[('val1', 'min'), (2, 'sum'), (2, 'size')]
. 1)for t in a.columns.values
Schleifen über die Spalten für die zweite Spaltet == (2, 'sum')
; 2)map(str, t)
giltstr()
für jede "Ebene", was zu('2', 'sum')
; 3)"_".join(('2','sum'))
ergibt "2_sum",Eine allgemeine Lösung für mehrere Ebenen und gemischte Typen:
quelle
df.columns = ['_'.join(tuple(map(str, t))).rstrip('_') for t in df.columns.values]
Vielleicht etwas spät, aber wenn Sie sich keine Sorgen über doppelte Spaltennamen machen:
quelle
(year, )
und(tempf, amax)
Wenn Sie ein Trennzeichen im Namen zwischen den Ebenen haben möchten, funktioniert diese Funktion gut.
quelle
df.columns = ["_".join(filter(None, c)) for c in df.columns]
Nach @jxstanford und @ tvt173 habe ich eine Schnellfunktion geschrieben, die den Trick ausführen sollte, unabhängig von den Spaltennamen von string / int:
quelle
Sie können auch wie folgt vorgehen. Betrachten Sie
df
als Ihren Datenrahmen und nehmen Sie einen zweistufigen Index an (wie in Ihrem Beispiel).quelle
Ich werde einen direkten Weg teilen, der für mich funktioniert hat.
quelle
Definieren Sie eine Funktion wie die folgende, um einen MultiIndex innerhalb einer Kette anderer DataFrame-Methoden zu reduzieren:
Verwenden Sie dann die
pipe
Methode , um diese Funktion in der Kette der DataFrame-Methoden nachgroupby
undagg
vor allen anderen Methoden in der Kette anzuwenden:quelle
Eine weitere einfache Routine.
quelle