Bagaimana cara memutar kerangka data?
- Apa itu pivot?
- Bagaimana cara saya melakukan pivot?
- Apakah ini poros?
- Format panjang ke format lebar?
Saya telah melihat banyak pertanyaan yang menanyakan tentang tabel pivot. Bahkan jika mereka tidak tahu bahwa mereka bertanya tentang tabel pivot, biasanya mereka bertanya. Hampir tidak mungkin untuk menulis pertanyaan dan jawaban kanonik yang mencakup semua aspek pivoting ...
... Tapi aku akan mencobanya.
Permasalahan dari pertanyaan dan jawaban yang ada adalah seringkali pertanyaan difokuskan pada nuansa yang sulit digeneralisasikan oleh OP untuk menggunakan sejumlah jawaban baik yang ada. Namun, tidak ada jawaban yang mencoba memberikan penjelasan yang komprehensif (karena itu tugas yang menakutkan)
Lihat beberapa contoh dari pencarian google saya
- Pertanyaan dan jawaban yang bagus. Tetapi jawabannya hanya menjawab pertanyaan spesifik dengan sedikit penjelasan.
- Dalam pertanyaan ini, OP berkaitan dengan output dari pivot. Yaitu tampilan kolom. OP ingin terlihat seperti R. Ini tidak terlalu membantu bagi pengguna panda.
- Pertanyaan lain yang layak tetapi jawabannya berfokus pada satu metode, yaitu
pd.DataFrame.pivot
Jadi, setiap kali seseorang menelusuri, pivot
mereka mendapatkan hasil sporadis yang kemungkinan besar tidak akan menjawab pertanyaan spesifik mereka.
Mendirikan
Anda mungkin memperhatikan bahwa saya secara mencolok menamai kolom saya dan nilai kolom yang relevan agar sesuai dengan bagaimana saya akan berputar dalam jawaban di bawah ini.
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
Pertanyaan
Mengapa saya mendapatkan
ValueError: Index contains duplicate entries, cannot reshape
Bagaimana cara saya melakukan pivot
df
sehinggacol
nilainya adalah kolom,row
nilai adalah indeks, dan mean darival0
nilainya?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
Bagaimana cara saya melakukan pivot
df
sehinggacol
nilainya adalah kolom,row
nilai adalah indeks, mean darival0
nilai, dan nilai yang hilang adalah0
?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
Bisakah saya mendapatkan sesuatu selain
mean
, seperti mungkinsum
?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
Dapatkah saya melakukan lebih dari satu agregasi pada satu waktu?
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
Dapatkah saya menggabungkan lebih dari beberapa kolom nilai?
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
Bisakah Membagi dengan beberapa kolom?
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
Atau
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
Dapatkah saya menggabungkan frekuensi di mana kolom dan baris muncul bersamaan, alias "tabulasi silang"?
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
Bagaimana cara mengonversi DataFrame dari panjang ke lebar dengan berputar HANYA pada dua kolom? Diberikan,
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
Yang diharapkan akan terlihat seperti ini
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
Bagaimana cara meratakan beberapa indeks ke indeks tunggal setelahnya
pivot
Dari
1 2 1 1 2 a 2 1 1 b 2 1 0 c 1 0 0
Untuk
1|1 2|1 2|2 a 2 1 1 b 2 1 0 c 1 0 0
Jawaban
Kami mulai dengan menjawab pertanyaan pertama:
pertanyaan 1
Mengapa saya mendapatkan
ValueError: Index contains duplicate entries, cannot reshape
Ini terjadi karena panda mencoba mengindeks ulang salah satu objek columns
atau index
dengan entri duplikat. Ada berbagai metode untuk digunakan yang dapat melakukan pivot. Beberapa di antaranya tidak cocok jika ada duplikat kunci yang diminta untuk melakukan pivot. Sebagai contoh. Pertimbangkan pd.DataFrame.pivot
. Saya tahu ada entri duplikat yang berbagi nilai row
dan col
:
df.duplicated(['row', 'col']).any()
True
Jadi saat saya pivot
menggunakan
df.pivot(index='row', columns='col', values='val0')
Saya mendapatkan kesalahan yang disebutkan di atas. Faktanya, saya mendapatkan kesalahan yang sama ketika saya mencoba melakukan tugas yang sama dengan:
df.set_index(['row', 'col'])['val0'].unstack()
Berikut adalah daftar idiom yang dapat kita gunakan untuk melakukan pivot
pd.DataFrame.groupby
+pd.DataFrame.unstack
- Pendekatan umum yang baik untuk melakukan hampir semua jenis pivot
- Anda menentukan semua kolom yang akan membentuk tingkat baris yang diputar dan tingkat kolom dalam satu grup dengan. Anda mengikuti itu dengan memilih kolom yang tersisa yang ingin Anda agregat dan fungsi yang Anda inginkan untuk melakukan agregasi. Akhirnya, Anda
unstack
tingkat yang Anda inginkan dalam indeks kolom.
pd.DataFrame.pivot_table
- Versi yang dimuliakan
groupby
dengan API yang lebih intuitif. Bagi banyak orang, ini adalah pendekatan yang disukai. Dan merupakan pendekatan yang dimaksudkan oleh pengembang. - Tentukan level baris, level kolom, nilai yang akan digabungkan, dan fungsi untuk melakukan agregasi.
- Versi yang dimuliakan
pd.DataFrame.set_index
+pd.DataFrame.unstack
- Nyaman dan intuitif bagi sebagian orang (termasuk saya). Tidak dapat menangani kunci yang dikelompokkan duplikat.
- Mirip dengan
groupby
paradigma, kami menetapkan semua kolom yang pada akhirnya akan menjadi tingkat baris atau kolom dan menyetelnya menjadi indeks. Kami kemudianunstack
tingkat yang kami inginkan di kolom. Jika level indeks yang tersisa atau level kolom tidak unik, metode ini akan gagal.
pd.DataFrame.pivot
- Sangat mirip dengan
set_index
yang berbagi batasan kunci duplikat. API juga sangat terbatas. Hanya membutuhkan nilai-nilai skalar untukindex
,columns
,values
. - Mirip dengan
pivot_table
metode di mana kami memilih baris, kolom, dan nilai untuk pivot. Namun, kami tidak dapat menggabungkan dan jika salah satu baris atau kolom tidak unik, metode ini akan gagal.
- Sangat mirip dengan
pd.crosstab
- Ini adalah versi khusus dari
pivot_table
dan dalam bentuknya yang paling murni adalah cara paling intuitif untuk melakukan beberapa tugas.
- Ini adalah versi khusus dari
pd.factorize
+np.bincount
- Ini adalah teknik yang sangat maju yang sangat tidak jelas tetapi sangat cepat. Ini tidak dapat digunakan dalam semua keadaan, tetapi jika dapat digunakan dan Anda merasa nyaman menggunakannya, Anda akan menuai hasil kinerja.
pd.get_dummies
+pd.DataFrame.dot
- Saya menggunakan ini untuk melakukan tabulasi silang dengan cerdik.
Contoh
Apa yang akan saya lakukan untuk setiap jawaban dan pertanyaan berikutnya adalah menjawabnya dengan menggunakan pd.DataFrame.pivot_table
. Kemudian saya akan memberikan alternatif untuk melakukan tugas yang sama.
Pertanyaan 3
Bagaimana cara saya melakukan pivot
df
sehinggacol
nilainya adalah kolom,row
nilai adalah indeks, mean darival0
nilai, dan nilai yang hilang adalah0
?
pd.DataFrame.pivot_table
fill_value
tidak disetel secara default. Saya cenderung mengaturnya dengan tepat. Dalam hal ini saya setel ke0
. Perhatikan bahwa saya melewatkan pertanyaan 2 karena sama dengan jawaban ini tanpafill_value
aggfunc='mean'
adalah default dan saya tidak perlu menyetelnya. Saya memasukkannya untuk menjadi eksplisit.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)
Pertanyaan 4
Bisakah saya mendapatkan sesuatu selain
mean
, seperti mungkinsum
?
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)
Pertanyaan 5
Dapatkah saya melakukan lebih dari satu agregasi pada satu waktu?
Perhatikan bahwa for pivot_table
dan crosstab
saya harus meneruskan daftar callable. Di sisi lain, groupby.agg
dapat mengambil string untuk sejumlah fungsi khusus. groupby.agg
juga akan mengambil callable yang sama yang kami berikan kepada yang lain, tetapi seringkali lebih efisien untuk memanfaatkan nama fungsi string karena ada efisiensi yang bisa diperoleh.
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')
Pertanyaan 6
Dapatkah saya menggabungkan lebih dari beberapa kolom nilai?
pd.DataFrame.pivot_table
kita lulusvalues=['val0', 'val1']
tapi kita bisa meninggalkannya sepenuhnyadf.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)
Pertanyaan 7
Bisakah Membagi dengan beberapa kolom?
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)
Pertanyaan 8
Bisakah Membagi dengan beberapa kolom?
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
karena kumpulan kunci unik untuk baris dan kolomdf.set_index( ['key', 'row', 'item', 'col'] )['val0'].unstack(['item', 'col']).fillna(0).sort_index(1)
Pertanyaan 9
Dapatkah saya menggabungkan frekuensi di mana kolom dan baris muncul bersamaan, alias "tabulasi silang"?
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
Pertanyaan 10
Bagaimana cara mengonversi DataFrame dari panjang ke lebar dengan berputar HANYA pada dua kolom?
Langkah pertama adalah menetapkan nomor ke setiap baris - nomor ini akan menjadi indeks baris dari nilai tersebut dalam hasil pivot. Ini dilakukan dengan menggunakan 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
Langkah kedua adalah menggunakan kolom yang baru dibuat sebagai indeks untuk dipanggil 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
Pertanyaan 11
Bagaimana cara meratakan beberapa indeks ke indeks tunggal setelahnya
pivot
Jika columns
mengetik object
dengan stringjoin
df.columns = df.columns.map('|'.join)
lain format
df.columns = df.columns.map('{0[0]}|{0[1]}'.format)
Untuk memperluas jawaban @ piRSquared versi lain dari Pertanyaan 10
Pertanyaan 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
Keluaran:
0 1 2
A
1 a b c
2 a b None
3 a None None
5 c None None
Menggunakan df.groupby
danpd.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
Atau alternatif yang jauh lebih baik menggunakan pd.pivot_table
dengandf.squeeze.
t = df.pivot_table(index='A',values='B',aggfunc=list).squeeze()
out = pd.DataFrame(t.tolist(),index=t.index)