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ı left
ve right
ortak 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 left
kullanılır ve eksik veriler right
NaN 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 right
kullanılır ve eksik veriler left
NaN 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 left
yalnı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) left
sahipse keyLeft
ve right
sahipse, keyRight
bunun yerine key
aşağıdakileri belirtmeniz left_on
ve right_on
bağı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 keyLeft
gelen left
ve keyRight
gelen right
sadece birinin istiyorsanız keyLeft
veya 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, keyLeft
eksik 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_on
ve right_on
uygun 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
, join
veconcat
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_on
ve right_on
gerektiğ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 left
adlandı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.join
Dizinde birleştirilecek varsayılanları kullanabilirsiniz . DataFrame.join
varsayı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 lsuffix
ve 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.concat
gönderiye bakın .
Genelleme: merge
birden ç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.concat
endeksi 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
concat
hı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, join
benzersiz olmayan anahtarları işleyebildiği için kullanabiliriz ( join
DataFrames'ları dizinlerinde birleştirir; merge
baş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