Veri çerçevesi nasıl özetlenir?
- Pivot nedir?
- Nasıl dönebilirim?
- Bu bir pivot mu?
- Uzun biçimden geniş biçime?
Pivot tablolar hakkında soran birçok soru gördüm. Pivot tablolar hakkında soru sorduklarını bilmeseler bile, genellikle sorarlar. Döndürmenin tüm yönlerini kapsayan kanonik bir soru ve cevap yazmak neredeyse imkansızdır ...
... Ama bir şans vereceğim.
Mevcut sorular ve cevaplarla ilgili sorun, sorunun çoğu zaman, OP'nin mevcut iyi cevapların bir kısmını kullanmak için genellemede sorun yaşadığı bir nüansa odaklanmasıdır. Bununla birlikte, cevapların hiçbiri kapsamlı bir açıklama yapmaya çalışmaz (çünkü göz korkutucu bir görevdir)
Google aramamdan birkaç örneğe bakın
- Güzel soru ve cevap. Ancak yanıt, yalnızca belirli bir soruyu çok az açıklamayla yanıtlar.
- Bu soruda OP, pivotun çıktısı ile ilgilenir. Yani sütunların nasıl göründüğü. OP, R'ye benzemesini istedi. Bu pandalar için pek yararlı değil.
- Başka bir iyi soru ama cevap bir yönteme odaklanıyor, yani
pd.DataFrame.pivot
Bu nedenle, birisi aradığında pivot
, belirli sorularını cevaplamayacak olan düzensiz sonuçlar alır.
Kurmak
Aşağıdaki cevapları nasıl özetleyeceğime karşılık olarak sütunlarımı ve ilgili sütun değerlerini açıkça adlandırdığımı fark edebilirsiniz.
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
Soru (lar)
Neden alıyorum
ValueError: Index contains duplicate entries, cannot reshape
Nasıl dönebilecek yapmak
df
böylecol
değerlerin sütunlar olup,row
değerler endeksi, ve ortalamaval0
değerleridir?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
Nasıl dönebilecek yapmak
df
böylecol
değerlerin sütunlar olup,row
değer alabilmekte, endeksin ortalama vardırval0
değerlerdir ve eksik değerlerdir0
?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
mean
Belki dışında başka bir şey alabilir miyimsum
?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
Bir seferde birden fazla toplama yapabilir miyim?
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
Birden çok değer sütunu üzerinden toplayabilir miyim?
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
Birden çok sütuna göre alt bölümlere ayrılabilir mi?
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
Veya
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
Sütun ve satırların birlikte görülme sıklığını, yani "çapraz tablo" olarak toplayabilir miyim?
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
Bir DataFrame'i SADECE iki sütun üzerinde özetleyerek uzundan genişe nasıl dönüştürebilirim? Verilen,
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
Beklenen bir şeye benzemeli
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
Birden çok dizini tek dizine nasıl düzleştiririm sonra
pivot
Nereden
1 2 1 1 2 a 2 1 1 b 2 1 0 c 1 0 0
İçin
1|1 2|1 2|2 a 2 1 1 b 2 1 0 c 1 0 0
Yanıtlar
İlk soruyu cevaplayarak başlıyoruz:
Soru 1
Neden alıyorum
ValueError: Index contains duplicate entries, cannot reshape
Bunun nedeni, pandaların bir columns
veya index
yinelenen girdilere sahip bir nesneyi yeniden dizinlemeye çalışmasıdır . Bir pivot gerçekleştirebilecek çeşitli yöntemler vardır. Bazıları, üzerinde dönmesi istenen anahtarların kopyaları olduğunda pek uygun değildir. Örneğin. Düşünün pd.DataFrame.pivot
. row
Ve col
değerlerini paylaşan yinelenen girişler olduğunu biliyorum :
df.duplicated(['row', 'col']).any()
True
Ben Yani pivot
kullanarak
df.pivot(index='row', columns='col', values='val0')
Yukarıda belirtilen hatayı alıyorum. Aslında, aynı görevi aşağıdakilerle yapmaya çalıştığımda aynı hatayı alıyorum:
df.set_index(['row', 'col'])['val0'].unstack()
Özetlemek için kullanabileceğimiz deyimlerin bir listesi
pd.DataFrame.groupby
+pd.DataFrame.unstack
- Hemen hemen her tür pivot yapmak için iyi bir genel yaklaşım
- Özetlenmiş satır düzeylerini ve sütun düzeylerini oluşturacak tüm sütunları tek bir grupta belirtirsiniz. Bunu, toplamak istediğiniz kalan sütunları ve toplamayı gerçekleştirmek istediğiniz işlevleri seçerek takip edersiniz. Son olarak,
unstack
sütun indeksinde olmasını istediğiniz seviyeler.
pd.DataFrame.pivot_table
groupby
Daha sezgisel API ile övülen bir sürümü . Birçok insan için tercih edilen yaklaşım budur. Ve geliştiriciler tarafından amaçlanan yaklaşım budur.- Satır düzeyini, sütun düzeylerini, toplanacak değerleri ve toplamaları gerçekleştirmek için işlevleri belirtin.
pd.DataFrame.set_index
+pd.DataFrame.unstack
- Bazıları için uygun ve sezgisel (kendim dahil). Yinelenen gruplanmış anahtarlar işlenemez.
groupby
Paradigmaya benzer şekilde, sonunda satır veya sütun seviyeleri olacak tüm sütunları belirleriz ve bunları indeks olarak belirleriz. Ardındanunstack
sütunlarda istediğimiz seviyelere geliyoruz. Kalan dizin seviyeleri veya sütun seviyeleri benzersiz değilse, bu yöntem başarısız olacaktır.
pd.DataFrame.pivot
set_index
Yinelenen anahtar sınırlamasını paylaşmasına çok benzer . API de çok sınırlıdır. Sadece için sayıl değerlerini alırindex
,columns
,values
.pivot_table
Yönteme benzer şekilde, üzerinde özetlenecek satırları, sütunları ve değerleri seçiyoruz. Ancak, kümeleme yapamayız ve satırlar veya sütunlar benzersiz değilse bu yöntem başarısız olur.
pd.crosstab
- Bu,
pivot_table
en saf haliyle özel bir sürümü birkaç görevi gerçekleştirmenin en sezgisel yoludur.
- Bu,
pd.factorize
+np.bincount
- Bu, çok belirsiz ancak çok hızlı olan oldukça gelişmiş bir tekniktir. Her koşulda kullanılamaz, ancak kullanılabildiğinde ve rahatça kullandığınızda, performans ödüllerini alacaksınız.
pd.get_dummies
+pd.DataFrame.dot
- Bunu akıllıca çapraz tablolama yapmak için kullanıyorum.
Örnekler
Sonraki her cevap ve soru için yapacağım şey onu kullanarak cevaplamaktır pd.DataFrame.pivot_table
. Sonra aynı görevi yerine getirmek için alternatifler sunacağım.
Soru 3
Nasıl dönebilecek yapmak
df
böylecol
değerlerin sütunlar olup,row
değer alabilmekte, endeksin ortalama vardırval0
değerlerdir ve eksik değerlerdir0
?
pd.DataFrame.pivot_table
fill_value
varsayılan olarak ayarlanmamıştır. Uygun şekilde ayarlama eğilimindeyim. Bu durumda ben ayarladım0
. Dikkat edin, soru 2'yi atladığıma dikkat edin , çünkü bu cevapla aynıdır.fill_value
aggfunc='mean'
varsayılandır ve bunu ayarlamama gerek yoktu. Açık olması için ekledim.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)
Soru 4
mean
Belki dışında başka bir şey alabilir miyimsum
?
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)
Soru 5
Bir seferde birden fazla toplama yapabilir miyim?
Söz konusu Bildirimi pivot_table
ve crosstab
ben callables listesini iletmek gerekiyordu. Öte yandan, groupby.agg
sınırlı sayıda özel işlev için dizeler alabilir. groupby.agg
diğerlerine aktardığımız aynı çağrılabilirleri de alırdı, ancak elde edilecek verimlilikler olduğu için string işlev adlarını kullanmak genellikle daha etkilidir.
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')
Soru 6
Birden çok değer sütunu üzerinden toplayabilir miyim?
pd.DataFrame.pivot_table
Geçtikvalues=['val0', 'val1']
ama bunu tamamen bırakabilirdikdf.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)
Soru 7
Birden çok sütuna göre alt bölümlere ayrılabilir mi?
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)
Soru 8
Birden çok sütuna göre alt bölümlere ayrılabilir mi?
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
çünkü anahtar seti hem satırlar hem de sütunlar için benzersizdirdf.set_index( ['key', 'row', 'item', 'col'] )['val0'].unstack(['item', 'col']).fillna(0).sort_index(1)
Soru 9
Sütun ve satırların birlikte görülme sıklığını, yani "çapraz tablo" olarak toplayabilir miyim?
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
Soru 10
Bir DataFrame'i SADECE iki sütun üzerinde özetleyerek uzundan genişe nasıl dönüştürebilirim?
İlk adım, her satıra bir sayı atamaktır - bu sayı, özetlenmiş sonuçtaki bu değerin satır dizini olacaktır. Bu, şu şekilde yapılır 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
İkinci adım, yeni oluşturulan sütunu çağırmak için dizin olarak kullanmaktır 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
Soru 11
Birden çok dizini tek dizine nasıl düzleştiririm sonra
pivot
Eğer columns
tip object
dizeylejoin
df.columns = df.columns.map('|'.join)
Başka format
df.columns = df.columns.map('{0[0]}|{0[1]}'.format)
@ PiRSquared'in yanıtını genişletmek için Soru 10'un başka bir versiyonu
Soru 10.1
Veri çerçevesi:
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
Çıktı:
0 1 2
A
1 a b c
2 a b None
3 a None None
5 c None None
kullanılması df.groupby
vepd.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
Veya çok iyi bir alternatif kullanılarak pd.pivot_table
iledf.squeeze.
t = df.pivot_table(index='A',values='B',aggfunc=list).squeeze()
out = pd.DataFrame(t.tolist(),index=t.index)