Jak obrócić 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 pytania i odpowiedzi jest to, że często pytanie koncentruje się na niuansie, że OP ma problemy uogólniania w celu wykorzystania wielu istniejących dobrych odpowiedzi. Jednak żadna z odpowiedzi nie próbuje dać wyczerpującego wyjaśnienia (ponieważ jest to trudne zadanie) [34]}
Spójrz na kilka przykładów z mojego szukaj w google
-
jak obracać ramkę danych w pandach?
- dobre pytanie i odpowiedź. Ale odpowiedź odpowiada tylko na konkretne pytanie z małym wyjaśnieniem.
-
tabela przestawna pandy do ramki danych
- 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.
-
pandy obracają ramkę danych, powielają wiersze
- kolejne porządne pytanie, ale odpowiedź skupia się na jednej metodzie, a mianowicie
pd.DataFrame.pivot
- kolejne porządne pytanie, ale odpowiedź skupia się na jednej metodzie, a mianowicie
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. Zwróć uwagę, aby zapoznać się z tym, gdzie znajdują się nazwy kolumn, aby uzyskać wyniki, których szukasz za.
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, abycol
wartości były kolumnami,row
wartości są indeksem, a średnia zval0
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 {[15] } 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 kolumn wartości?
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
1 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ą wartości row
i col
:
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
-
[108]}dobre ogólne podejście do robienia prawie każdego rodzaju pivot
- podajesz wszystkie kolumny, które będą stanowić obracane poziomy wierszy i poziomów kolumn 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
- 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 wtedyunstack
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ć. Jednak my nie można agregować i jeśli wiersze lub kolumny nie są unikalne, ta metoda nie powiedzie się.
- 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ć stosowany w wszystkie okoliczności, 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
. Następnie dostarczę alternatywy do wykonania to samo zadanie.
Pytanie 3
Jak obrócić
df
tak, abycol
wartości były kolumnami,row
wartości są indeksem, średnia zval0
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
. Zauważ, że 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że {66]}?
-
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 cross_tab
musiałem przekazać listę połączeń. Z drugiej strony groupby.agg
jest w stanie pobierać łańcuchy dla ograniczonej liczby funkcji specjalnych. groupby.agg
wziąłby również te same wywołania, które przekazaliśmy innym, ale często bardziej wydajne jest wykorzystanie nazw funkcji łańcuchowych, ponieważ istnieją wydajności, które mają być / align = "left" /
-
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 całkowicie pominąćdf.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
Można podzielić przez wiele kolumny?
-
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
Czy można podzielić przez wiele kolumn?
-
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 "tabulacja krzyżowa"?
-
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.cross_tab
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
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
2017-11-14 17:13:35