Posting ini bertujuan untuk memberikan pembaca sebuah primer tentang penggabungan rasa SQL dengan panda, cara menggunakannya, dan kapan tidak menggunakannya.
Secara khusus, inilah yang akan dikirim melalui pos ini:
Apa yang tidak akan dikirim melalui pos ini:
- Diskusi dan pengaturan waktu terkait kinerja (untuk saat ini). Sebagian besar menyebutkan alternatif yang lebih baik, jika perlu.
- Menangani sufiks, menghapus kolom tambahan, mengganti nama keluaran, dan kasus penggunaan khusus lainnya. Ada pos lain (baca: lebih baik) yang berurusan dengan itu, jadi cari tahu!
Catatan
Kebanyakan contoh default untuk operasi Gabung INNER sambil menunjukkan berbagai fitur, kecuali ditentukan lain.
Selanjutnya, semua DataFrames di sini dapat disalin dan direplikasi sehingga Anda dapat bermain dengannya. Juga, lihat posting ini
tentang cara membaca DataFrames dari clipboard Anda.
Terakhir, semua representasi visual dari operasi JOIN telah digambar tangan menggunakan Google Drawings. Inspirasi dari sini .
Cukup Bicara, cukup tunjukkan saya bagaimana menggunakan merge
!
Mendirikan
np.random.seed(0)
left = pd.DataFrame({'key': ['A', 'B', 'C', 'D'], 'value': np.random.randn(4)})
right = pd.DataFrame({'key': ['B', 'D', 'E', 'F'], 'value': np.random.randn(4)})
left
key value
0 A 1.764052
1 B 0.400157
2 C 0.978738
3 D 2.240893
right
key value
0 B 1.867558
1 D -0.977278
2 E 0.950088
3 F -0.151357
Demi kesederhanaan, kolom kunci memiliki nama yang sama (untuk saat ini).
Sebuah INNER JOIN diwakili oleh
Perhatikan
ini, bersama dengan angka-angka yang akan datang semua mengikuti konvensi ini:
- biru menunjukkan baris yang ada di hasil gabungan
- merah menunjukkan baris yang dikecualikan dari hasil (yaitu, dihapus)
- hijau menunjukkan nilai yang hilang yang diganti dengan NaN dalam hasilnya
Untuk melakukan INNER JOIN, panggil merge
DataFrame kiri, tentukan DataFrame kanan dan tombol join (paling tidak) sebagai argumen.
left.merge(right, on='key')
# Or, if you want to be explicit
# left.merge(right, on='key', how='inner')
key value_x value_y
0 B 0.400157 1.867558
1 D 2.240893 -0.977278
Ini hanya mengembalikan baris dari left
dan right
yang berbagi kunci umum (dalam contoh ini, "B" dan "D).
Sebuah KIRI Outer JOIN , atau LEFT JOIN diwakili oleh
Ini dapat dilakukan dengan menentukan how='left'
.
left.merge(right, on='key', how='left')
key value_x value_y
0 A 1.764052 NaN
1 B 0.400157 1.867558
2 C 0.978738 NaN
3 D 2.240893 -0.977278
Perhatikan penempatan NaN dengan hati-hati di sini. Jika Anda menentukan how='left'
, maka hanya kunci dari left
yang digunakan, dan data yang hilang dari right
digantikan oleh NaN.
Dan demikian pula, untuk GABUNGAN LUAR TEPAT , atau GABUNG TEPAT yang ...
... sebutkan how='right'
:
left.merge(right, on='key', how='right')
key value_x value_y
0 B 0.400157 1.867558
1 D 2.240893 -0.977278
2 E NaN 0.950088
3 F NaN -0.151357
Di sini, kunci dari right
digunakan, dan data yang hilang dari left
digantikan oleh NaN.
Akhirnya, untuk FULL OUTER JOIN , diberikan oleh
tentukan how='outer'
.
left.merge(right, on='key', how='outer')
key value_x value_y
0 A 1.764052 NaN
1 B 0.400157 1.867558
2 C 0.978738 NaN
3 D 2.240893 -0.977278
4 E NaN 0.950088
5 F NaN -0.151357
Ini menggunakan kunci dari kedua frame, dan NaN dimasukkan untuk baris yang hilang di keduanya.
Dokumentasi merangkum berbagai gabungan ini dengan baik:
GABUNGAN Lainnya - KIRI-Tidak Termasuk, KANAN-Tidak, dan FULL-Tidak Termasuk / ANTI BERGABUNG
Jika Anda membutuhkan GABUNGAN KIRI-Kecualikan dan GABUNGAN KECUALI -KECUALI dalam dua langkah.
Untuk KIRI-Tidak Termasuk BERGABUNG, diwakili sebagai
Mulailah dengan melakukan LEFT OUTER JOIN dan kemudian filterkan (tidak termasuk!) Baris yang left
hanya berasal dari ,
(left.merge(right, on='key', how='left', indicator=True)
.query('_merge == "left_only"')
.drop('_merge', 1))
key value_x value_y
0 A 1.764052 NaN
2 C 0.978738 NaN
Dimana,
left.merge(right, on='key', how='left', indicator=True)
key value_x value_y _merge
0 A 1.764052 NaN left_only
1 B 0.400157 1.867558 both
2 C 0.978738 NaN left_only
3 D 2.240893 -0.977278 both
Dan juga, untuk BERGABUNG DENGAN KANAN,
(left.merge(right, on='key', how='right', indicator=True)
.query('_merge == "right_only"')
.drop('_merge', 1))
key value_x value_y
2 E NaN 0.950088
3 F NaN -0.151357
Terakhir, jika Anda diminta untuk melakukan penggabungan yang hanya mempertahankan kunci dari kiri atau kanan, tetapi tidak keduanya (TKI, melakukan ANTI-GABUNG ),
Anda bisa melakukan ini dengan cara yang sama—
(left.merge(right, on='key', how='outer', indicator=True)
.query('_merge != "both"')
.drop('_merge', 1))
key value_x value_y
0 A 1.764052 NaN
2 C 0.978738 NaN
4 E NaN 0.950088
5 F NaN -0.151357
Nama berbeda untuk kolom kunci
Jika kolom kunci diberi nama yang berbeda — misalnya, left
memiliki keyLeft
, dan right
memiliki keyRight
bukannya key
—kemudian Anda harus menentukan left_on
dan right_on
sebagai argumen alih-alih on
:
left2 = left.rename({'key':'keyLeft'}, axis=1)
right2 = right.rename({'key':'keyRight'}, axis=1)
left2
keyLeft value
0 A 1.764052
1 B 0.400157
2 C 0.978738
3 D 2.240893
right2
keyRight value
0 B 1.867558
1 D -0.977278
2 E 0.950088
3 F -0.151357
left2.merge(right2, left_on='keyLeft', right_on='keyRight', how='inner')
keyLeft value_x keyRight value_y
0 B 0.400157 B 1.867558
1 D 2.240893 D -0.977278
Menghindari kolom kunci duplikat dalam output
Saat menggabungkan keyLeft
dari left
dan keyRight
dari right
, jika Anda hanya menginginkan salah satu keyLeft
atau keyRight
(tetapi tidak keduanya) dalam output, Anda bisa mulai dengan mengatur indeks sebagai langkah awal.
left3 = left2.set_index('keyLeft')
left3.merge(right2, left_index=True, right_on='keyRight')
value_x keyRight value_y
0 0.400157 B 1.867558
1 2.240893 D -0.977278
Bandingkan ini dengan output dari perintah sebelum (ini, output dari left2.merge(right2, left_on='keyLeft', right_on='keyRight', how='inner')
), Anda akan melihat keyLeft
ada yang hilang. Anda bisa mengetahui kolom mana yang akan disimpan berdasarkan indeks frame mana yang ditetapkan sebagai kunci. Ini mungkin penting ketika, katakanlah, melakukan beberapa operasi GABUNG LUAR.
Menggabungkan hanya satu kolom dari salah satu DataFrames
Sebagai contoh, pertimbangkan
right3 = right.assign(newcol=np.arange(len(right)))
right3
key value newcol
0 B 1.867558 0
1 D -0.977278 1
2 E 0.950088 2
3 F -0.151357 3
Jika Anda diharuskan untuk menggabungkan hanya "new_val" (tanpa ada kolom lain), Anda biasanya dapat hanya subset kolom sebelum menggabungkan:
left.merge(right3[['key', 'newcol']], on='key')
key value newcol
0 B 0.400157 0
1 D 2.240893 1
Jika Anda melakukan LEFT OUTER JOIN, solusi yang lebih berkinerja akan melibatkan map
:
# left['newcol'] = left['key'].map(right3.set_index('key')['newcol']))
left.assign(newcol=left['key'].map(right3.set_index('key')['newcol']))
key value newcol
0 A 1.764052 NaN
1 B 0.400157 0.0
2 C 0.978738 NaN
3 D 2.240893 1.0
Seperti disebutkan, ini mirip dengan, tetapi lebih cepat dari
left.merge(right3[['key', 'newcol']], on='key', how='left')
key value newcol
0 A 1.764052 NaN
1 B 0.400157 0.0
2 C 0.978738 NaN
3 D 2.240893 1.0
Menggabungkan beberapa kolom
Untuk bergabung di lebih dari satu kolom, tentukan daftar untuk on
(atau left_on
dan right_on
, jika sesuai).
left.merge(right, on=['key1', 'key2'] ...)
Atau, jika namanya berbeda,
left.merge(right, left_on=['lkey1', 'lkey2'], right_on=['rkey1', 'rkey2'])
merge*
Operasi dan fungsi lain yang bermanfaat
Bagian ini hanya membahas dasar-dasarnya saja, dan dirancang hanya untuk memuaskan selera Anda. Untuk contoh dan kasus, lihat dokumentasi di merge
, join
, danconcat
serta link ke spesifikasi fungsi.
Berbasis indeks * -JOIN (+ indeks-kolom merge
s)
Mendirikan
np.random.seed([3, 14])
left = pd.DataFrame({'value': np.random.randn(4)}, index=['A', 'B', 'C', 'D'])
right = pd.DataFrame({'value': np.random.randn(4)}, index=['B', 'D', 'E', 'F'])
left.index.name = right.index.name = 'idxkey'
left
value
idxkey
A -0.602923
B -0.402655
C 0.302329
D -0.524349
right
value
idxkey
B 0.543843
D 0.013135
E -0.326498
F 1.385076
Biasanya, gabungan pada indeks akan terlihat seperti ini:
left.merge(right, left_index=True, right_index=True)
value_x value_y
idxkey
B -0.402655 0.543843
D -0.524349 0.013135
Dukungan untuk nama indeks
Jika indeks Anda dinamai, maka pengguna v0.23 juga dapat menentukan nama level untuk on
(atau left_on
dan right_on
jika perlu).
left.merge(right, on='idxkey')
value_x value_y
idxkey
B -0.402655 0.543843
D -0.524349 0.013135
Menggabungkan pada indeks satu, kolom yang lain
Dimungkinkan (dan cukup sederhana) untuk menggunakan indeks satu, dan kolom lainnya, untuk melakukan penggabungan. Sebagai contoh,
left.merge(right, left_on='key1', right_index=True)
Atau sebaliknya ( right_on=...
dan left_index=True
).
right2 = right.reset_index().rename({'idxkey' : 'colkey'}, axis=1)
right2
colkey value
0 B 0.543843
1 D 0.013135
2 E -0.326498
3 F 1.385076
left.merge(right2, left_index=True, right_on='colkey')
value_x colkey value_y
0 -0.402655 B 0.543843
1 -0.524349 D 0.013135
Dalam kasus khusus ini, indeks untuk left
dinamai, sehingga Anda juga dapat menggunakan nama indeks dengan left_on
, seperti ini:
left.merge(right2, left_on='idxkey', right_on='colkey')
value_x colkey value_y
0 -0.402655 B 0.543843
1 -0.524349 D 0.013135
DataFrame.join
Selain itu, ada opsi ringkas lainnya. Anda dapat menggunakan DataFrame.join
default untuk bergabung dengan indeks. DataFrame.join
apakah LEFT OUTER JOIN secara default, jadi how='inner'
perlu di sini.
left.join(right, how='inner', lsuffix='_x', rsuffix='_y')
value_x value_y
idxkey
B -0.402655 0.543843
D -0.524349 0.013135
Perhatikan bahwa saya perlu menentukan lsuffix
dan rsuffix
argumen karena join
kalau tidak akan keluar:
left.join(right)
ValueError: columns overlap but no suffix specified: Index(['value'], dtype='object')
Karena nama kolomnya sama. Ini tidak akan menjadi masalah jika nama mereka berbeda.
left.rename(columns={'value':'leftvalue'}).join(right, how='inner')
leftvalue value
idxkey
B -0.402655 0.543843
D -0.524349 0.013135
pd.concat
Terakhir, sebagai alternatif untuk gabungan berbasis indeks, Anda dapat menggunakan pd.concat
:
pd.concat([left, right], axis=1, sort=False, join='inner')
value value
idxkey
B -0.402655 0.543843
D -0.524349 0.013135
Hapus join='inner'
jika Anda memerlukan FULL OUTER JOIN (default):
pd.concat([left, right], axis=1, sort=False)
value value
A -0.602923 NaN
B -0.402655 0.543843
C 0.302329 NaN
D -0.524349 0.013135
E NaN -0.326498
F NaN 1.385076
Untuk informasi lebih lanjut, lihat posting kanonik ini pd.concat
oleh @piRSquared .
Generalisasi: merge
ing beberapa DataFrames
Seringkali, situasi muncul ketika beberapa DataFrame akan digabung bersama. Naif, ini bisa dilakukan dengan chaining merge
panggilan:
df1.merge(df2, ...).merge(df3, ...)
Namun, ini dengan cepat keluar dari tangan banyak DataFrames. Selain itu, mungkin perlu digeneralisasi untuk jumlah DataFrames yang tidak diketahui.
Di sini saya memperkenalkan pd.concat
untuk sambungan multi-arah pada kunci unik , dan DataFrame.join
untuk sambungan multi-arah pada kunci non-unik . Pertama, pengaturannya.
# Setup.
np.random.seed(0)
A = pd.DataFrame({'key': ['A', 'B', 'C', 'D'], 'valueA': np.random.randn(4)})
B = pd.DataFrame({'key': ['B', 'D', 'E', 'F'], 'valueB': np.random.randn(4)})
C = pd.DataFrame({'key': ['D', 'E', 'J', 'C'], 'valueC': np.ones(4)})
dfs = [A, B, C]
# Note, the "key" column values are unique, so the index is unique.
A2 = A.set_index('key')
B2 = B.set_index('key')
C2 = C.set_index('key')
dfs2 = [A2, B2, C2]
Penggabungan multiway pada kunci unik (atau indeks)
Jika kunci Anda (di sini, kunci tersebut bisa berupa kolom atau indeks) adalah unik, maka Anda dapat menggunakannya pd.concat
. Perhatikan bahwa pd.concat
bergabung dengan DataFrames pada indeks .
# merge on `key` column, you'll need to set the index before concatenating
pd.concat([
df.set_index('key') for df in dfs], axis=1, join='inner'
).reset_index()
key valueA valueB valueC
0 D 2.240893 -0.977278 1.0
# merge on `key` index
pd.concat(dfs2, axis=1, sort=False, join='inner')
valueA valueB valueC
key
D 2.240893 -0.977278 1.0
Hilangkan join='inner'
untuk GABUNGAN LUAR LENGKAP. Perhatikan bahwa Anda tidak dapat menentukan gabungan LEFT atau RIGHT OUTER (jika Anda memerlukannya, gunakan join
, dijelaskan di bawah).
Multiway menggabungkan kunci dengan duplikat
concat
cepat, tetapi memiliki kekurangannya. Itu tidak bisa menangani duplikat.
A3 = pd.DataFrame({'key': ['A', 'B', 'C', 'D', 'D'], 'valueA': np.random.randn(5)})
pd.concat([df.set_index('key') for df in [A3, B, C]], axis=1, join='inner')
ValueError: Shape of passed values is (3, 4), indices imply (3, 2)
Dalam situasi ini, kita dapat menggunakan join
karena dapat menangani kunci non-unik (perhatikan bahwa join
bergabung dengan DataFrames pada indeks mereka; ia memanggil di merge
bawah tenda dan melakukan LEFT OUTER JOIN kecuali ditentukan lain).
# join on `key` column, set as the index first
# For inner join. For left join, omit the "how" argument.
A.set_index('key').join(
[df.set_index('key') for df in (B, C)], how='inner').reset_index()
key valueA valueB valueC
0 D 2.240893 -0.977278 1.0
# join on `key` index
A3.set_index('key').join([B2, C2], how='inner')
valueA valueB valueC
key
D 1.454274 -0.977278 1.0
D 0.761038 -0.977278 1.0
concat
danmerge
dengan parameter arah menjadihorizontal
atauvertical
.axis=1
dan apaaxis=0
?merge
danconcat
dan sumbu dan apa pun. Namun, seperti yang ditunjukkan @eliu, itu semua hanya konsep gabungan yang sama dengan "kiri" dan "kanan" dan "horisontal" atau "vertikal". Saya, secara pribadi, harus melihat ke dalam dokumentasi setiap kali saya harus mengingat "sumbu"0
mana dan mana1
.