Wie schwenke ich einen Datenrahmen?
- Was ist Pivot?
- Wie schwenke ich?
- Ist das ein Dreh- und Angelpunkt?
- Langformat zu Breitformat?
Ich habe viele Fragen zu Pivot-Tabellen gesehen. Selbst wenn sie nicht wissen, dass sie nach Pivot-Tabellen fragen, sind sie es normalerweise. Es ist praktisch unmöglich, eine kanonische Frage und Antwort zu schreiben, die alle Aspekte des Schwenkens umfasst ...
... Aber ich werde es versuchen.
Das Problem bei vorhandenen Fragen und Antworten besteht darin, dass sich die Frage häufig auf eine Nuance konzentriert, die das OP nur schwer verallgemeinern kann, um eine Reihe der vorhandenen guten Antworten zu verwenden. Keine der Antworten versucht jedoch, eine umfassende Erklärung zu geben (da dies eine entmutigende Aufgabe ist).
Schauen Sie sich einige Beispiele aus meiner Google-Suche an
- Gute Frage und Antwort. Die Antwort beantwortet die spezifische Frage jedoch nur mit wenig Erklärung.
- In dieser Frage befasst sich das OP mit der Ausgabe des Pivots. Nämlich wie die Spalten aussehen. OP wollte, dass es wie R aussieht. Dies ist für Pandas-Benutzer nicht sehr hilfreich.
- Eine andere anständige Frage, aber die Antwort konzentriert sich auf eine Methode, nämlich
pd.DataFrame.pivot
Wenn jemand nach etwas sucht pivot
, erhält er sporadische Ergebnisse, die seine spezifische Frage wahrscheinlich nicht beantworten.
Installieren
Möglicherweise stellen Sie fest, dass ich meine Spalten und relevanten Spaltenwerte auffällig benannt habe, um zu entsprechen, wie ich in den folgenden Antworten schwenken werde.
import numpy as np
import pandas as pd
from numpy.core.defchararray import add
np.random.seed([3,1415])
n = 20
cols = np.array(['key', 'row', 'item', 'col'])
arr1 = (np.random.randint(5, size=(n, 4)) // [2, 1, 2, 1]).astype(str)
df = pd.DataFrame(
add(cols, arr1), columns=cols
).join(
pd.DataFrame(np.random.rand(n, 2).round(2)).add_prefix('val')
)
print(df)
key row item col val0 val1
0 key0 row3 item1 col3 0.81 0.04
1 key1 row2 item1 col2 0.44 0.07
2 key1 row0 item1 col0 0.77 0.01
3 key0 row4 item0 col2 0.15 0.59
4 key1 row0 item2 col1 0.81 0.64
5 key1 row2 item2 col4 0.13 0.88
6 key2 row4 item1 col3 0.88 0.39
7 key1 row4 item1 col1 0.10 0.07
8 key1 row0 item2 col4 0.65 0.02
9 key1 row2 item0 col2 0.35 0.61
10 key2 row0 item2 col1 0.40 0.85
11 key2 row4 item1 col2 0.64 0.25
12 key0 row2 item2 col3 0.50 0.44
13 key0 row4 item1 col4 0.24 0.46
14 key1 row3 item2 col3 0.28 0.11
15 key0 row3 item1 col1 0.31 0.23
16 key0 row0 item2 col3 0.86 0.01
17 key0 row4 item0 col3 0.64 0.21
18 key2 row2 item2 col0 0.13 0.45
19 key0 row2 item0 col4 0.37 0.70
Fragen)
Warum bekomme ich
ValueError: Index contains duplicate entries, cannot reshape
Wie schwenke ich
df
so, dass diecol
Werte Spalten,row
Werte der Index und der Mittelwertval0
die Werte sind?col col0 col1 col2 col3 col4 row row0 0.77 0.605 NaN 0.860 0.65 row2 0.13 NaN 0.395 0.500 0.25 row3 NaN 0.310 NaN 0.545 NaN row4 NaN 0.100 0.395 0.760 0.24
Wie schwenke ich
df
so, dass diecol
Werte Spalten,row
Werte der Index, der Mittelwertval0
der Werte und fehlende Werte sind0
?col col0 col1 col2 col3 col4 row row0 0.77 0.605 0.000 0.860 0.65 row2 0.13 0.000 0.395 0.500 0.25 row3 0.00 0.310 0.000 0.545 0.00 row4 0.00 0.100 0.395 0.760 0.24
Kann ich etwas anderes bekommen als
mean
vielleichtsum
?col col0 col1 col2 col3 col4 row row0 0.77 1.21 0.00 0.86 0.65 row2 0.13 0.00 0.79 0.50 0.50 row3 0.00 0.31 0.00 1.09 0.00 row4 0.00 0.10 0.79 1.52 0.24
Kann ich mehr als eine Aggregation gleichzeitig durchführen?
sum mean col col0 col1 col2 col3 col4 col0 col1 col2 col3 col4 row row0 0.77 1.21 0.00 0.86 0.65 0.77 0.605 0.000 0.860 0.65 row2 0.13 0.00 0.79 0.50 0.50 0.13 0.000 0.395 0.500 0.25 row3 0.00 0.31 0.00 1.09 0.00 0.00 0.310 0.000 0.545 0.00 row4 0.00 0.10 0.79 1.52 0.24 0.00 0.100 0.395 0.760 0.24
Kann ich über mehrere Wertespalten aggregieren?
val0 val1 col col0 col1 col2 col3 col4 col0 col1 col2 col3 col4 row row0 0.77 0.605 0.000 0.860 0.65 0.01 0.745 0.00 0.010 0.02 row2 0.13 0.000 0.395 0.500 0.25 0.45 0.000 0.34 0.440 0.79 row3 0.00 0.310 0.000 0.545 0.00 0.00 0.230 0.00 0.075 0.00 row4 0.00 0.100 0.395 0.760 0.24 0.00 0.070 0.42 0.300 0.46
Kann durch mehrere Spalten unterteilen?
item item0 item1 item2 col col2 col3 col4 col0 col1 col2 col3 col4 col0 col1 col3 col4 row row0 0.00 0.00 0.00 0.77 0.00 0.00 0.00 0.00 0.00 0.605 0.86 0.65 row2 0.35 0.00 0.37 0.00 0.00 0.44 0.00 0.00 0.13 0.000 0.50 0.13 row3 0.00 0.00 0.00 0.00 0.31 0.00 0.81 0.00 0.00 0.000 0.28 0.00 row4 0.15 0.64 0.00 0.00 0.10 0.64 0.88 0.24 0.00 0.000 0.00 0.00
Oder
item item0 item1 item2 col col2 col3 col4 col0 col1 col2 col3 col4 col0 col1 col3 col4 key row key0 row0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.86 0.00 row2 0.00 0.00 0.37 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.50 0.00 row3 0.00 0.00 0.00 0.00 0.31 0.00 0.81 0.00 0.00 0.00 0.00 0.00 row4 0.15 0.64 0.00 0.00 0.00 0.00 0.00 0.24 0.00 0.00 0.00 0.00 key1 row0 0.00 0.00 0.00 0.77 0.00 0.00 0.00 0.00 0.00 0.81 0.00 0.65 row2 0.35 0.00 0.00 0.00 0.00 0.44 0.00 0.00 0.00 0.00 0.00 0.13 row3 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.28 0.00 row4 0.00 0.00 0.00 0.00 0.10 0.00 0.00 0.00 0.00 0.00 0.00 0.00 key2 row0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.40 0.00 0.00 row2 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.13 0.00 0.00 0.00 row4 0.00 0.00 0.00 0.00 0.00 0.64 0.88 0.00 0.00 0.00 0.00 0.00
Kann ich die Häufigkeit aggregieren, in der Spalte und Zeilen zusammen auftreten, auch als "Kreuztabelle" bezeichnet?
col col0 col1 col2 col3 col4 row row0 1 2 0 1 1 row2 1 0 2 1 2 row3 0 1 0 2 0 row4 0 1 2 2 1
Wie konvertiere ich einen DataFrame von lang nach breit, indem ich NUR zwei Spalten schwenke? Gegeben,
np.random.seed([3, 1415]) df2 = pd.DataFrame({'A': list('aaaabbbc'), 'B': np.random.choice(15, 8)}) df2 A B 0 a 0 1 a 11 2 a 2 3 a 11 4 b 10 5 b 10 6 b 14 7 c 7
Das erwartete sollte ungefähr so aussehen
a b c 0 0.0 10.0 7.0 1 11.0 10.0 NaN 2 2.0 14.0 NaN 3 11.0 NaN NaN
Wie reduziere ich den Mehrfachindex danach auf einen Einzelindex?
pivot
Von
1 2 1 1 2 a 2 1 1 b 2 1 0 c 1 0 0
Zu
1|1 2|1 2|2 a 2 1 1 b 2 1 0 c 1 0 0
Antworten
Wir beginnen mit der Beantwortung der ersten Frage:
Frage 1
Warum bekomme ich
ValueError: Index contains duplicate entries, cannot reshape
Dies liegt daran, dass Pandas versucht, entweder ein Objekt columns
oder ein index
Objekt mit doppelten Einträgen neu zu indizieren . Es gibt verschiedene Methoden, mit denen ein Pivot ausgeführt werden kann. Einige von ihnen sind nicht gut geeignet, wenn es Duplikate der Schlüssel gibt, auf denen sie zum Schwenken aufgefordert werden. Zum Beispiel. Überlegen Sie pd.DataFrame.pivot
. Ich weiß, dass es doppelte Einträge gibt, die die Werte row
und teilen col
:
df.duplicated(['row', 'col']).any()
True
Also wenn ich pivot
benutze
df.pivot(index='row', columns='col', values='val0')
Ich erhalte den oben genannten Fehler. Tatsächlich erhalte ich denselben Fehler, wenn ich versuche, dieselbe Aufgabe auszuführen mit:
df.set_index(['row', 'col'])['val0'].unstack()
Hier ist eine Liste von Redewendungen, mit denen wir schwenken können
pd.DataFrame.groupby
+pd.DataFrame.unstack
- Guter allgemeiner Ansatz für nahezu jede Art von Pivot
- Sie geben alle Spalten an, aus denen die geschwenkten Zeilen- und Spaltenebenen in einer Gruppe von bestehen. Anschließend wählen Sie die verbleibenden Spalten aus, die Sie aggregieren möchten, und die Funktionen, die Sie aggregieren möchten. Schließlich geben Sie
unstack
die Ebenen an, die Sie im Spaltenindex haben möchten.
pd.DataFrame.pivot_table
- Eine verherrlichte Version von
groupby
mit intuitiverer API. Für viele Menschen ist dies der bevorzugte Ansatz. Und ist der beabsichtigte Ansatz der Entwickler. - Geben Sie Zeilenebene, Spaltenebene, zu aggregierende Werte und Funktion (en) an, um Aggregationen durchzuführen.
- Eine verherrlichte Version von
pd.DataFrame.set_index
+pd.DataFrame.unstack
- Bequem und intuitiv für einige (ich eingeschlossen). Doppelte gruppierte Schlüssel können nicht verarbeitet werden.
- Ähnlich wie im
groupby
Paradigma geben wir alle Spalten an, die möglicherweise entweder Zeilen- oder Spaltenebenen sind, und legen diese als Index fest. Wir haben dannunstack
die Ebenen, die wir in den Spalten wollen. Wenn entweder die verbleibenden Index- oder Spaltenebenen nicht eindeutig sind, schlägt diese Methode fehl.
pd.DataFrame.pivot
- Sehr ähnlich,
set_index
da es die Einschränkung des doppelten Schlüssels teilt. Die API ist ebenfalls sehr begrenzt. Es dauert nur skalare Werte fürindex
,columns
,values
. - Ähnlich wie bei der
pivot_table
Methode wählen wir Zeilen, Spalten und Werte aus, auf die geschwenkt werden soll. Wir können jedoch nicht aggregieren. Wenn Zeilen oder Spalten nicht eindeutig sind, schlägt diese Methode fehl.
- Sehr ähnlich,
pd.crosstab
- Dies ist eine spezielle Version von
pivot_table
und in ihrer reinsten Form die intuitivste Möglichkeit, mehrere Aufgaben auszuführen.
- Dies ist eine spezielle Version von
pd.factorize
+np.bincount
- Dies ist eine hochentwickelte Technik, die sehr dunkel, aber sehr schnell ist. Es kann nicht unter allen Umständen verwendet werden, aber wenn es verwendet werden kann und Sie damit vertraut sind, werden Sie die Leistungsprämien ernten.
pd.get_dummies
+pd.DataFrame.dot
- Ich benutze dies, um geschickt Kreuztabellen durchzuführen.
Beispiele
Was ich für jede nachfolgende Antwort und Frage tun werde, ist, sie mit zu beantworten pd.DataFrame.pivot_table
. Dann werde ich Alternativen bereitstellen, um dieselbe Aufgabe auszuführen.
Frage 3
Wie schwenke ich
df
so, dass diecol
Werte Spalten,row
Werte der Index, der Mittelwertval0
der Werte und fehlende Werte sind0
?
pd.DataFrame.pivot_table
fill_value
ist nicht standardmäßig eingestellt. Ich neige dazu, es angemessen einzustellen. In diesem Fall habe ich es eingestellt0
. Beachten Sie, dass ich Frage 2 übersprungen habe , da sie mit der Antwort ohne übereinstimmtfill_value
aggfunc='mean'
ist die Standardeinstellung und ich musste sie nicht einstellen. Ich habe es ausdrücklich aufgenommen.df.pivot_table( values='val0', index='row', columns='col', fill_value=0, aggfunc='mean') col col0 col1 col2 col3 col4 row row0 0.77 0.605 0.000 0.860 0.65 row2 0.13 0.000 0.395 0.500 0.25 row3 0.00 0.310 0.000 0.545 0.00 row4 0.00 0.100 0.395 0.760 0.24
pd.DataFrame.groupby
df.groupby(['row', 'col'])['val0'].mean().unstack(fill_value=0)
pd.crosstab
pd.crosstab( index=df['row'], columns=df['col'], values=df['val0'], aggfunc='mean').fillna(0)
Frage 4
Kann ich etwas anderes bekommen als
mean
vielleichtsum
?
pd.DataFrame.pivot_table
df.pivot_table( values='val0', index='row', columns='col', fill_value=0, aggfunc='sum') col col0 col1 col2 col3 col4 row row0 0.77 1.21 0.00 0.86 0.65 row2 0.13 0.00 0.79 0.50 0.50 row3 0.00 0.31 0.00 1.09 0.00 row4 0.00 0.10 0.79 1.52 0.24
pd.DataFrame.groupby
df.groupby(['row', 'col'])['val0'].sum().unstack(fill_value=0)
pd.crosstab
pd.crosstab( index=df['row'], columns=df['col'], values=df['val0'], aggfunc='sum').fillna(0)
Frage 5
Kann ich mehr als eine Aggregation gleichzeitig durchführen?
Beachten Sie, dass für pivot_table
und crosstab
ich die Liste der Callables übergeben musste. Auf der anderen Seite groupby.agg
können Zeichenfolgen für eine begrenzte Anzahl von Sonderfunktionen verwendet werden. groupby.agg
hätte auch die gleichen Callables verwendet, die wir an die anderen weitergegeben haben, aber es ist oft effizienter, die Namen der Zeichenfolgenfunktionen zu nutzen, da Effizienzsteigerungen erzielt werden müssen.
pd.DataFrame.pivot_table
df.pivot_table( values='val0', index='row', columns='col', fill_value=0, aggfunc=[np.size, np.mean]) size mean col col0 col1 col2 col3 col4 col0 col1 col2 col3 col4 row row0 1 2 0 1 1 0.77 0.605 0.000 0.860 0.65 row2 1 0 2 1 2 0.13 0.000 0.395 0.500 0.25 row3 0 1 0 2 0 0.00 0.310 0.000 0.545 0.00 row4 0 1 2 2 1 0.00 0.100 0.395 0.760 0.24
pd.DataFrame.groupby
df.groupby(['row', 'col'])['val0'].agg(['size', 'mean']).unstack(fill_value=0)
pd.crosstab
pd.crosstab( index=df['row'], columns=df['col'], values=df['val0'], aggfunc=[np.size, np.mean]).fillna(0, downcast='infer')
Frage 6
Kann ich über mehrere Wertespalten aggregieren?
pd.DataFrame.pivot_table
Wir gehen vorbei,values=['val0', 'val1']
aber wir hätten das komplett weglassen könnendf.pivot_table( values=['val0', 'val1'], index='row', columns='col', fill_value=0, aggfunc='mean') val0 val1 col col0 col1 col2 col3 col4 col0 col1 col2 col3 col4 row row0 0.77 0.605 0.000 0.860 0.65 0.01 0.745 0.00 0.010 0.02 row2 0.13 0.000 0.395 0.500 0.25 0.45 0.000 0.34 0.440 0.79 row3 0.00 0.310 0.000 0.545 0.00 0.00 0.230 0.00 0.075 0.00 row4 0.00 0.100 0.395 0.760 0.24 0.00 0.070 0.42 0.300 0.46
pd.DataFrame.groupby
df.groupby(['row', 'col'])['val0', 'val1'].mean().unstack(fill_value=0)
Frage 7
Kann durch mehrere Spalten unterteilen?
pd.DataFrame.pivot_table
df.pivot_table( values='val0', index='row', columns=['item', 'col'], fill_value=0, aggfunc='mean') item item0 item1 item2 col col2 col3 col4 col0 col1 col2 col3 col4 col0 col1 col3 col4 row row0 0.00 0.00 0.00 0.77 0.00 0.00 0.00 0.00 0.00 0.605 0.86 0.65 row2 0.35 0.00 0.37 0.00 0.00 0.44 0.00 0.00 0.13 0.000 0.50 0.13 row3 0.00 0.00 0.00 0.00 0.31 0.00 0.81 0.00 0.00 0.000 0.28 0.00 row4 0.15 0.64 0.00 0.00 0.10 0.64 0.88 0.24 0.00 0.000 0.00 0.00
pd.DataFrame.groupby
df.groupby( ['row', 'item', 'col'] )['val0'].mean().unstack(['item', 'col']).fillna(0).sort_index(1)
Frage 8
Kann durch mehrere Spalten unterteilen?
pd.DataFrame.pivot_table
df.pivot_table( values='val0', index=['key', 'row'], columns=['item', 'col'], fill_value=0, aggfunc='mean') item item0 item1 item2 col col2 col3 col4 col0 col1 col2 col3 col4 col0 col1 col3 col4 key row key0 row0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.86 0.00 row2 0.00 0.00 0.37 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.50 0.00 row3 0.00 0.00 0.00 0.00 0.31 0.00 0.81 0.00 0.00 0.00 0.00 0.00 row4 0.15 0.64 0.00 0.00 0.00 0.00 0.00 0.24 0.00 0.00 0.00 0.00 key1 row0 0.00 0.00 0.00 0.77 0.00 0.00 0.00 0.00 0.00 0.81 0.00 0.65 row2 0.35 0.00 0.00 0.00 0.00 0.44 0.00 0.00 0.00 0.00 0.00 0.13 row3 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.28 0.00 row4 0.00 0.00 0.00 0.00 0.10 0.00 0.00 0.00 0.00 0.00 0.00 0.00 key2 row0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.40 0.00 0.00 row2 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.13 0.00 0.00 0.00 row4 0.00 0.00 0.00 0.00 0.00 0.64 0.88 0.00 0.00 0.00 0.00 0.00
pd.DataFrame.groupby
df.groupby( ['key', 'row', 'item', 'col'] )['val0'].mean().unstack(['item', 'col']).fillna(0).sort_index(1)
pd.DataFrame.set_index
weil der Schlüsselsatz sowohl für Zeilen als auch für Spalten eindeutig istdf.set_index( ['key', 'row', 'item', 'col'] )['val0'].unstack(['item', 'col']).fillna(0).sort_index(1)
Frage 9
Kann ich die Häufigkeit aggregieren, in der Spalte und Zeilen zusammen auftreten, auch als "Kreuztabelle" bezeichnet?
pd.DataFrame.pivot_table
df.pivot_table(index='row', columns='col', fill_value=0, aggfunc='size') col col0 col1 col2 col3 col4 row row0 1 2 0 1 1 row2 1 0 2 1 2 row3 0 1 0 2 0 row4 0 1 2 2 1
pd.DataFrame.groupby
df.groupby(['row', 'col'])['val0'].size().unstack(fill_value=0)
pd.crosstab
pd.crosstab(df['row'], df['col'])
pd.factorize
+np.bincount
# get integer factorization `i` and unique values `r` # for column `'row'` i, r = pd.factorize(df['row'].values) # get integer factorization `j` and unique values `c` # for column `'col'` j, c = pd.factorize(df['col'].values) # `n` will be the number of rows # `m` will be the number of columns n, m = r.size, c.size # `i * m + j` is a clever way of counting the # factorization bins assuming a flat array of length # `n * m`. Which is why we subsequently reshape as `(n, m)` b = np.bincount(i * m + j, minlength=n * m).reshape(n, m) # BTW, whenever I read this, I think 'Bean, Rice, and Cheese' pd.DataFrame(b, r, c) col3 col2 col0 col1 col4 row3 2 0 0 1 0 row2 1 2 1 0 2 row0 1 0 1 2 1 row4 2 2 0 1 1
pd.get_dummies
pd.get_dummies(df['row']).T.dot(pd.get_dummies(df['col'])) col0 col1 col2 col3 col4 row0 1 2 0 1 1 row2 1 0 2 1 2 row3 0 1 0 2 0 row4 0 1 2 2 1
Frage 10
Wie konvertiere ich einen DataFrame von lang nach breit, indem ich NUR zwei Spalten schwenke?
Der erste Schritt besteht darin, jeder Zeile eine Nummer zuzuweisen. Diese Nummer ist der Zeilenindex dieses Werts im Pivot-Ergebnis. Dies geschieht mit GroupBy.cumcount
:
df2.insert(0, 'count', df.groupby('A').cumcount())
df2
count A B
0 0 a 0
1 1 a 11
2 2 a 2
3 3 a 11
4 0 b 10
5 1 b 10
6 2 b 14
7 0 c 7
Der zweite Schritt besteht darin, die neu erstellte Spalte als aufzurufenden Index zu verwenden DataFrame.pivot
.
df2.pivot(*df)
# df.pivot(index='count', columns='A', values='B')
A a b c
count
0 0.0 10.0 7.0
1 11.0 10.0 NaN
2 2.0 14.0 NaN
3 11.0 NaN NaN
Frage 11
Wie reduziere ich den Mehrfachindex danach auf einen Einzelindex?
pivot
Wenn columns
Typ object
mit Stringjoin
df.columns = df.columns.map('|'.join)
sonst format
df.columns = df.columns.map('{0[0]}|{0[1]}'.format)
Um die Antwort von @ piRSquared um eine andere Version von Frage 10 zu erweitern
Frage 10.1
DataFrame:
d = data = {'A': {0: 1, 1: 1, 2: 1, 3: 2, 4: 2, 5: 3, 6: 5},
'B': {0: 'a', 1: 'b', 2: 'c', 3: 'a', 4: 'b', 5: 'a', 6: 'c'}}
df = pd.DataFrame(d)
A B
0 1 a
1 1 b
2 1 c
3 2 a
4 2 b
5 3 a
6 5 c
Ausgabe:
0 1 2
A
1 a b c
2 a b None
3 a None None
5 c None None
Verwenden von df.groupby
undpd.Series.tolist
t = df.groupby('A')['B'].apply(list)
out = pd.DataFrame(t.tolist(),index=t.index)
out
0 1 2
A
1 a b c
2 a b None
3 a None None
5 c None None
Oder eine viel bessere Alternative pd.pivot_table
mitdf.squeeze.
t = df.pivot_table(index='A',values='B',aggfunc=list).squeeze()
out = pd.DataFrame(t.tolist(),index=t.index)