Bu yazı, okuyuculara pandalarla SQL aromalı birleştirme, nasıl kullanılacağı ve kullanılmadığı zaman bir astar vermeyi amaçlamaktadır.
Özellikle, bu yazının içinden geçecekler:
Bu yazı ne geçmeyecek:
- Performansla ilgili tartışmalar ve zamanlamalar (şimdilik). Çoğunlukla dikkate değer, uygun olan yerlerde daha iyi alternatiflerden bahseder.
- Son ekleri işleme, fazladan sütunları kaldırma, çıktıları yeniden adlandırma ve diğer özel kullanım durumları. Bununla ilgili başka (daha iyi: daha iyi) yayınlar var, bu yüzden anlayın!
Not
Aksi belirtilmedikçe, çoğu örnek varsayılan olarak çeşitli özellikleri gösterirken INNER JOIN işlemleri için varsayılan değerdir.
Ayrıca, buradaki tüm DataFrame'ler kopyalanabilir ve çoğaltılabilir, böylece onlarla oynayabilirsiniz. Ayrıca bakınız bu yazıyı
panonuzdan DataFrames okumak için nasıl.
Son olarak, JOIN işlemlerinin tüm görsel gösterimleri Google Çizimler kullanılarak elle çizilmiştir. Buradan ilham alın .
Yeter Konuşma, nasıl kullanılacağını bana göster merge!
Kurmak
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
Kolaylık olması açısından, anahtar sütun aynı ada sahiptir (şimdilik).
Bir INNER JOIN ,

Not
Bu, gelecek rakamlarla birlikte bu sözleşmeyi takip eder:
- mavi , birleştirme sonucunda bulunan satırları gösterir
- kırmızı , sonuçtan hariç tutulan satırları belirtir (yani, kaldırılır)
- yeşil , sonuçta NaN ile değiştirilen eksik değerleri gösterir
Bir INNER JOIN gerçekleştirmek için merge, sol DataFrame'i arayın , sağ DataFrame'i ve birleştirme anahtarını (en azından) bağımsız değişken olarak belirtin.
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
Bu döner gelen satırları leftve rightortak bir (bu örnekte, "B" ve "D) tuşuna paylaşır.
Bir sol dış birleşim veya SOL ile temsil edilir artır

Bu, belirtilerek yapılabilir 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
NaN'lerin buraya yerleştirildiğini dikkatlice not edin. Belirtirseniz how='left', yalnızca anahtarlar leftkullanılır ve eksik veriler rightNaN ile değiştirilir.
Ve benzer şekilde, bir DOĞRU DIŞ ORTAK veya SAĞ birleşim için ...

... belirtin 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
Burada, anahtarlar rightkullanılır ve eksik veriler leftNaN ile değiştirilir.
Son olarak, FULL OUTER JOIN için ,

belirtin 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
Bu, her iki karedeki anahtarları kullanır ve her iki satırdaki eksik satırlar için NaN'ler eklenir.
Belgeler bu çeşitli birleştirmeleri güzel bir şekilde özetlemektedir:

Diğer BAĞLANTILAR - SOL-Hariç, SAĞ-Hariç ve TAM Hariç / ANTI JOIN'ler
İki adımda SOL-HARİCİ JOIN'lara ve SAĞ- HARİCİ JOIN'lara ihtiyacınız varsa .
Olarak temsil edilen SOL-hariç JOIN için

Bir LEFT OUTER JOIN gerçekleştirerek ve leftyalnızca gelen satırları filtreleyerek (hariç!) ,
(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
Nerede,
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
Benzer şekilde, DOĞRU OLMAYAN BİR BİRLEŞME için,

(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
Son olarak, yalnızca soldan veya sağdan anahtarları tutan, ancak her ikisini birden olmayan bir birleştirme yapmanız gerekiyorsa (IOW, bir ANTI-JOIN gerçekleştirme ),

Bunu benzer şekilde yapabilirsiniz -
(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
Anahtar sütunlar için farklı adlar
Anahtar sütunlar farklı adlandırılırsa (örneğin, yerine) leftsahipse keyLeftve rightsahipse, keyRightbunun yerine keyaşağıdakileri belirtmeniz left_onve right_onbağımsız değişken olarak belirtmeniz gerekir 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
Çıktıda yinelenen anahtar sütunundan kaçınma
Üzerinde birleştirirken keyLeftgelen leftve keyRightgelen rightsadece birinin istiyorsanız keyLeftveya keyRightçıktıda (ama ikisini), bir ön adım olarak indeksini ayarlayarak başlayabilir.
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
Bunu komutun çıktısından hemen önce (bu çıktı, çıktısı ile left2.merge(right2, left_on='keyLeft', right_on='keyRight', how='inner')) karşılaştırın, keyLefteksik olduğunu fark edeceksiniz . Hangi karenin dizininin anahtar olarak ayarlandığına bağlı olarak hangi sütunun tutulacağını anlayabilirsiniz. Diyelim ki, bazı OUTER JOIN işlemlerinin yapılması önemli olabilir.
Yalnızca bir sütunu, DataFrames
Örneğin,
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
Yalnızca "new_val" değerini birleştirmeniz gerekiyorsa (diğer sütunlardan herhangi biri olmadan), birleştirmeden önce genellikle yalnızca sütunları alt kümeye ayarlayabilirsiniz:
left.merge(right3[['key', 'newcol']], on='key')
key value newcol
0 B 0.400157 0
1 D 2.240893 1
SOL DIŞ BİRLEŞME yapıyorsanız, daha performanslı bir çözüm mapşunları içerir :
# 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
Belirtildiği gibi, bu benzer, ancak daha hızlı
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
Birden çok sütunda birleştirme
Birden fazla sütun üzerinde katılmak için, bir listesini belirtin on(ya left_onve right_onuygun olanları).
left.merge(right, on=['key1', 'key2'] ...)
Veya isimler farklıysa,
left.merge(right, left_on=['lkey1', 'lkey2'], right_on=['rkey1', 'rkey2'])
Diğer faydalı merge*işlemler ve fonksiyonlar
Bu bölüm sadece temel bilgileri içerir ve sadece iştahınızı hafifletmek için tasarlanmıştır. Daha fazla örnek ve durumlar için, bkz belgelerine merge, joinveconcat aynı zamanda fonksiyon özellikleri bağlantılar gibi.
Dizin tabanlı * -JOIN (+ dizin sütunları merge)
Kurmak
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
Tipik olarak, dizindeki birleştirme şöyle görünür:
left.merge(right, left_index=True, right_index=True)
value_x value_y
idxkey
B -0.402655 0.543843
D -0.524349 0.013135
Dizin adları için destek
İşaret adlı, o zaman v0.23 kullanıcıların da seviye adını belirtebilirsiniz on(veya left_onve right_ongerektiği gibi).
left.merge(right, on='idxkey')
value_x value_y
idxkey
B -0.402655 0.543843
D -0.524349 0.013135
Birinin dizininde, diğerinin sütunlarında birleştirme
Birleştirme gerçekleştirmek için birinin dizinini ve diğerinin sütununu kullanmak mümkündür (ve oldukça basittir). Örneğin,
left.merge(right, left_on='key1', right_index=True)
Ya da tam tersi ( right_on=...ve 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
Bu özel durumda, dizini leftadlandırılır, böylece dizin adını şu şekilde de kullanabilirsiniz left_on:
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
Bunların yanında başka bir özlü seçenek daha var. DataFrame.joinDizinde birleştirilecek varsayılanları kullanabilirsiniz . DataFrame.joinvarsayılan olarak bir LEFT OUTER JOIN yapar, bu yüzden how='inner'burada gereklidir.
left.join(right, how='inner', lsuffix='_x', rsuffix='_y')
value_x value_y
idxkey
B -0.402655 0.543843
D -0.524349 0.013135
Ben aksi takdirde hata olur lsuffixve rsuffixçünkü argümanlar belirtmek için gerekli olduğunu unutmayın join:
left.join(right)
ValueError: columns overlap but no suffix specified: Index(['value'], dtype='object')
Sütun adları aynı olduğundan. Farklı isimlendirildikleri takdirde bu sorun olmaz.
left.rename(columns={'value':'leftvalue'}).join(right, how='inner')
leftvalue value
idxkey
B -0.402655 0.543843
D -0.524349 0.013135
pd.concat
Son olarak, dizin tabanlı birleşimlere alternatif olarak şunları kullanabilirsiniz 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
join='inner'TAM DIŞ BİRLEŞMEYE ihtiyacınız varsa atlayın (varsayılan):
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
Daha fazla bilgi için @piRSquared tarafından hazırlanan bu standart pd.concatgönderiye bakın .
Genelleme: mergebirden çok DataFrames oluşturma
Çoğu zaman, birden çok DataFrame'in bir araya getirilmesi durumunda bu durum ortaya çıkar. Safça, bu mergeçağrı zincirleme yoluyla yapılabilir :
df1.merge(df2, ...).merge(df3, ...)
Ancak, bu birçok DataFrame için çabucak kontrolden çıkar. Ayrıca, bilinmeyen sayıda DataFrame için genelleme yapmak gerekebilir.
Burada tanıtmak pd.concatçok yönlü katılıp için eşsiz anahtar ve DataFrame.joinçoklu yol üzerinde birleştiği benzersiz olmayan anahtarlar. İlk olarak, kurulum.
# 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]
Benzersiz anahtarlarda (veya dizinde) çok yönlü birleştirme
Anahtarlarınız (burada, anahtar bir sütun veya bir dizin olabilir) benzersizse, kullanabilirsiniz pd.concat. Not pd.concatendeksi DataFrames katılır .
# 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
Omit join='inner'tam dış için artır. SOL veya SAĞ DIŞ birleşimleri belirtemeyeceğinizi unutmayın (bunlara ihtiyacınız varsa join, aşağıda açıklananları kullanın ).
Yinelenen tuşlarda çok yönlü birleştirme
concathızlı, ama eksiklikleri var. Kopyaları işleyemez.
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)
Bu durumda, joinbenzersiz olmayan anahtarları işleyebildiği için kullanabiliriz ( joinDataFrames'ları dizinlerinde birleştirir; mergebaşlık altında çağırır ve aksi belirtilmedikçe bir SOL DIŞ birleşim yapar).
# 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