Jak obracać ramkę danych?
- Co to jest pivot?
- Jak się obracać?
- czy to pivot?
- długi format do szerokiego formatu?
Widziałem wiele pytań, które pytają o tabele przestawne. Nawet jeśli nie wiedzą, że pytają o tabele przestawne, zwykle tak jest. Jest to praktycznie niemożliwe, aby napisać kanoniczne pytanie i odpowiedź, która obejmuje wszystkie aspekty obrotu...
... Ale spróbuję.
Problem z istniejącymi pytaniami i odpowiedziami jest to, że często pytanie koncentruje się na niuansie, że OP ma problemy z uogólnieniem w celu wykorzystania liczby istniejących dobrych odpowiedzi. Jednak żadna z odpowiedzi nie próbuje dać wyczerpującego wyjaśnienia (ponieważ jest to trudne zadanie) [39]}
Spójrz na kilka przykładów z mojego szukaj w google
- Dobre pytanie i odpowiedź. Ale odpowiedź tylko odpowiedzi na konkretne pytanie z niewielkim wyjaśnieniem.
- W tym pytaniu OP dotyczy wyjścia Pivota. Mianowicie jak wyglądają kolumny. OP chciał, żeby wyglądało jak R. nie jest to zbyt pomocne dla użytkowników pand.
- kolejne porządne pytanie, ale odpowiedź skupia się na jednej metodzie, mianowicie
pd.DataFrame.pivot
Więc za każdym razem, gdy ktoś szuka pivot
otrzymuje sporadyczne wyniki, które prawdopodobnie nie odpowiedzą na jego konkretne pytanie.
Setup
Możesz zauważyć, że widocznie nazwałem moje kolumny i odpowiednie wartości kolumn, aby odpowiadały temu, jak będę się obracał w odpowiedziach poniżej.
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
Pytanie(y)
-
Dlaczego dostaję
ValueError: Index contains duplicate entries, cannot reshape
-
Jak obrócić
df
tak, aby wartościcol
były kolumny,row
wartości są indeksem, a średnia zval0
są wartościami?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
-
Jak obrócić
df
tak, abycol
wartości były kolumnami,row
wartości są indeksem, średnia z {[19] } są wartościami, a brakujące wartości to0
?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
-
Czy Mogę dostać coś innego niż
mean
, jak możesum
?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
-
Czy Mogę zrobić więcej, że jedna agregacja na raz?
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
-
Czy Mogę agregować wiele wartości kolumny?
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
-
Czy można podzielić na kilka kolumn?
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
-
Lub
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
-
Czy Mogę połączyć częstotliwość, w której kolumny i wiersze występują razem, aka "tabulacja krzyżowa"?
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
-
Jak przekonwertować ramkę danych z długiej na szeroką, obracając się tylko na dwóch kolumnach? Given,
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
Oczekiwany powinien wyglądać jak
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
-
Jak spłaszczyć indeks wielokrotności na pojedynczy indeks po
pivot
Od
1 2 1 1 2 a 2 1 1 b 2 1 0 c 1 0 0
Do
1|1 2|1 2|2 a 2 1 1 b 2 1 0 c 1 0 0
2 answers
Zaczynamy od odpowiedzi na pierwsze pytanie:
Pytanie 1
Dlaczego dostaję
ValueError: Index contains duplicate entries, cannot reshape
Dzieje się tak, ponieważ pandy próbują reindeksować obiekt columns
lub index
z duplikatami wpisów. Istnieją różne metody, które mogą wykonać obrót. Niektóre z nich nie są dobrze dostosowane do sytuacji, gdy istnieją duplikaty kluczy, w których jest proszony o obracanie się. Na przykład. Rozważ pd.DataFrame.pivot
. Wiem, że są duplikaty wpisów które dzielą row
i col
wartości:
df.duplicated(['row', 'col']).any()
True
Więc kiedy pivot
używam
df.pivot(index='row', columns='col', values='val0')
Dostaję błąd wymieniony powyżej. W rzeczywistości, dostaję ten sam błąd, gdy próbuję wykonać to samo zadanie z:
df.set_index(['row', 'col'])['val0'].unstack()
Oto lista idiomów, których możemy użyć do obracania]}
-
pd.DataFrame.groupby
+pd.DataFrame.unstack
-
[119]}dobre ogólne podejście do robienia prawie każdego rodzaju pivot
- podajesz wszystkie kolumny, które będzie stanowić poziomy wiersza i kolumny w jednej grupie przez. Następnie zaznaczając pozostałe kolumny, które chcesz agregować, oraz funkcje, które chcesz wykonać agregację. Na koniec, można
unstack
poziomy, które chcesz być w indeksie kolumny. -
pd.DataFrame.pivot_table
- gloryfikowana wersja
groupby
z bardziej intuicyjnym API. Dla wielu osób jest to preferowane podejście. I jest zamierzonym podejściem przez deweloperzy. - określa poziom wiersza, poziomy kolumn, wartości do agregacji oraz funkcje do agregacji.
- gloryfikowana wersja
-
pd.DataFrame.set_index
+pd.DataFrame.unstack
-
[119]}wygodne i intuicyjne dla niektórych (w tym mnie). Nie można obsługiwać zduplikowanych kluczy zgrupowanych.
- podobnie jak paradygmat
groupby
, określamy wszystkie kolumny, które będą w końcu poziomami wierszy lub kolumn i ustawiamy je jako indeks. My następnieunstack
poziomy, które chcemy w kolumnach. Jeśli pozostałe poziomy indeksów lub kolumny nie są unikalne, ta metoda nie powiedzie się. -
pd.DataFrame.pivot
- bardzo podobny do
set_index
w tym, że dzieli ograniczenie duplikatu klucza. Interfejs API jest również bardzo ograniczony. Przyjmuje tylko wartości skalarne dlaindex
,columns
,values
. - podobne do metody
pivot_table
, w której wybieramy wiersze, kolumny i wartości, na których mamy się obracać. Nie możemy jednak agregować i jeśli wiersze lub kolumny nie są unikalne, ta metoda zawiedzie.
- bardzo podobny do
-
pd.crosstab
- to wyspecjalizowana wersja
pivot_table
i w najczystszej formie jest najbardziej intuicyjnym sposobem wykonywania kilku zadań.
- to wyspecjalizowana wersja
-
pd.factorize
+np.bincount
- Jest to bardzo zaawansowana technika, która jest bardzo niejasna, ale bardzo szybka. Nie może być używane w każdych okolicznościach, ale kiedy można go używać i wygodnie z niego korzystać, będziesz czerpać korzyści z wydajności.
-
pd.get_dummies
+pd.DataFrame.dot
- używam tego do sprytnego wykonywania tabulacji krzyżowej.
Przykłady
To, co zamierzam zrobić dla każdej kolejnej odpowiedzi i pytania, to odpowiedzieć za pomocą pd.DataFrame.pivot_table
. Wtedy dostarczę alternatywy dla wykonaj to samo zadanie.
Pytanie 3
Jak obrócić
df
tak, abycol
wartości były kolumnami,row
wartości są indeksem, średnia z {[60] } są wartościami, a brakujące wartości to0
?
-
pd.DataFrame.pivot_table
-
fill_value
nie jest ustawiona domyślnie. Zazwyczaj ustawiam je odpowiednio. W tym przypadku ustawiłem go na0
. Uwaga pominąłem pytanie 2 ponieważ jest to to samo co ta odpowiedź bezfill_value
-
aggfunc='mean'
jest domyślne i nie musiałem go ustawiać. Dodałem to, żeby było jasne.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)
Pytanie 4
Czy Mogę dostać coś innego niż
mean
, jak możesum
?
-
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)
Pytanie 5
Czy Mogę zrobić więcej, że jedna agregacja na raz?
Zauważ, że dla pivot_table
I crosstab
musiałem przekazać listę połączeń. Z drugiej strony groupby.agg
jest w stanie pobierać łańcuchy dla ograniczonej liczby funkcji specjalnych. groupby.agg
również wziąłby to samo wywołania, które przekazaliśmy innym, ale często bardziej wydajne jest wykorzystanie nazw funkcji łańcuchowych, ponieważ można uzyskać wydajność.
-
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')
Pytanie 6
Czy Mogę agregować wiele kolumn wartości?
-
pd.DataFrame.pivot_table
mijamyvalues=['val0', 'val1']
ale mogliśmy to pominąć całkowiciedf.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)
Pytanie 7
Czy można podzielić na kilka kolumn?
-
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)
Pytanie 8
Można podzielić przez wiele kolumny?
-
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
ponieważ zestaw kluczy jest unikalny zarówno dla wierszy, jak i kolumndf.set_index( ['key', 'row', 'item', 'col'] )['val0'].unstack(['item', 'col']).fillna(0).sort_index(1)
Pytanie 9
Czy Mogę połączyć częstotliwość, w której kolumny i wiersze występują razem, aka " krzyż tabulacji"?
-
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
Pytanie 10
Jak przekonwertować ramkę danych z long na wide, obracając się tylko na dwóch kolumny?
Pierwszym krokiem jest przypisanie liczby do każdego wiersza - ta liczba będzie indeksem wiersza tej wartości w wyniku obrotu. Odbywa się to za pomocą 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
Drugim krokiem jest użycie nowo utworzonej kolumny jako indeksu do wywołania 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
Pytanie 11
Jak spłaszczyć indeks wielokrotności do pojedynczego indeksu po
pivot
If columns
type object
with string join
df.columns = df.columns.map('|'.join)
Else format
df.columns = df.columns.map('{0[0]}|{0[1]}'.format)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-12-18 23:01:53
Do rozszerzenia @piRSquared ' s answer kolejna wersja pytanie 10
Pytanie 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
Wyjście:
0 1 2
A
1 a b c
2 a b None
3 a None None
5 c None None
Za pomocą df.groupby
oraz pd.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
Lub
Znacznie lepszą alternatywą przy użyciu pd.pivot_table
z df.squeeze.
t = df.pivot_table(index='A',values='B',aggfunc=list).squeeze()
out = pd.DataFrame(t.tolist(),index=t.index)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-05 20:59:49