Pandalar Birleşiyor 101
- Pandalarla (
INNER
| (LEFT
|RIGHT
|FULL
)OUTER
) nasıl yapılırJOIN
? - Birleştirmeden sonra eksik satırlar için NaN'leri nasıl eklerim?
- Birleştirmeden sonra NaN'lerden nasıl kurtulurum?
- Endeks üzerinde birleşebilir miyim?
- Pandalarla çapraz birleşmek mi?
- Birden çok DataFrame'i nasıl birleştiririm?
merge
?join
?concat
?update
? DSÖ? Ne? Neden?!
... ve dahası. Pandaların birleştirme işlevinin çeşitli yönlerini soran bu yinelenen soruları gördüm. Günümüzde birleştirme ve çeşitli kullanım örnekleri ile ilgili bilgilerin çoğu, düzinelerce kötü yazılmış, aranamaz gönderiye bölünmüştür. Buradaki amaç, gelecek nesil için daha önemli bazı noktaları bir araya getirmektir.
Bu QnA, yaygın pandalar deyimleriyle ilgili bir dizi yararlı kullanıcı kılavuzunun bir sonraki bölümüdür ( pivotlama hakkındaki bu gönderiye ve daha sonra değineceğim birleştirme hakkındaki bu gönderiye bakın ).
Lütfen bu gönderinin dokümantasyonun yerini almadığını unutmayın, bu yüzden lütfen onu da okuyun! Örneklerden bazıları oradan alınmıştır.
Yanıtlar
Bu gönderi, okuyuculara pandalarla SQL-aromalı birleştirme, nasıl kullanılacağı ve ne zaman kullanılmayacağı hakkında bir başlangıç yapmayı amaçlamaktadır.
Özellikle, bu gönderinin içinden geçecekler:
Temel bilgiler - birleştirme türleri (SOL, SAĞ, DIŞ, İÇ)
- farklı sütun isimleriyle birleştirme
- çıktıda yinelenen birleştirme anahtarı sütunundan kaçınmak
Farklı koşullar altında indeks ile birleştirme
- adlandırılmış dizininizi etkili bir şekilde kullanarak
- birleştirme anahtarı, birinin dizini ve diğerinin sütunu olarak
Çok yollu, sütunlar ve dizinler üzerinde birleşir (benzersiz ve benzersiz olmayan)
İçin Önemli alternatifleri
merge
vejoin
Bu gönderinin üzerinden geçmeyecekler:
- Performansla ilgili tartışmalar ve zamanlamalar (şimdilik). Uygun olan yerlerde daha iyi alternatiflerden çoğunlukla kayda değer sözler.
- Sonekleri işleme, fazladan sütunları kaldırma, çıktıları yeniden adlandırma ve diğer özel kullanım durumları. Bununla ilgili başka (okuyun: daha iyi) gönderiler var, bu yüzden anlayın!
Not
Çoğu örnek, aksi belirtilmedikçe, çeşitli özellikleri gösterirken varsayılan olarak INNER JOIN işlemlerini kullanır.Ayrıca, buradaki tüm DataFrame'ler, onlarla oynayabilmeniz için kopyalanabilir ve çoğaltılabilir. Ayrıca bakınız bu yazıyı panonuzdan DataFrames okumak için nasıl.
Son olarak, JOIN işlemlerinin tüm görsel temsili Google Çizimler kullanılarak elle çizilmiştir. İlham buradan .
Bu kadar konuşma yeter, bana nasıl kullanılacağını 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
Basitlik adına, anahtar sütunun adı aynıdır (şimdilik).
Bir iç birleşim ile temsil edilir
Not
Bu, sonraki rakamlarla birlikte bu sözleşmeyi izler:
- mavi , birleştirme sonucunda bulunan satırları gösterir
- kırmızı , sonuçtan hariç tutulan (yani kaldırılan) satırları gösterir
- yeşil
NaN
, sonuçta s ile değiştirilen eksik değerleri gösterir
Bir INNER JOIN gerçekleştirmek için merge
, sağ DataFrame'i ve birleştirme anahtarını (en azından) bağımsız değişken olarak belirterek soldaki DataFrame'i çağırın.
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, yalnızca ortak bir anahtarı paylaşan left
ve right
bunlara ait satırları döndürür (bu örnekte, "B" ve "D).
Bir sol dış birleşim veya SOL ile temsil edilir artır
Bu, belirtilerek gerçekleştirilebilir 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 yerleştirilmesine dikkat edin. Eğer belirtirseniz how='left'
, o zaman sadece gelen anahtarları left
kullanılır ve içindeki eksik veriler right
NaN ile değiştirilir.
Ve benzer şekilde, RIGHT OUTER JOIN veya RIGHT JOIN için de ...
... 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 içindeki 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 çerçevedeki anahtarları kullanır ve her ikisinde de eksik satırlar için NaN'ler eklenir.
Belgeler, bu çeşitli birleşmeleri güzel bir şekilde özetliyor:
Diğer BİRLEŞTİRMELER - SOL-Hariç Tutan, Sağ Hariç Tutan ve TAM Hariç Tutan / ANTI BİRLEŞİMLERİ
İki adımda LEFT-Hariç JOIN'lere ve SAĞ-Hariç JOIN'lere ihtiyacınız varsa .
LEFT-Hariç JOIN için, şu şekilde temsil edilir:
Bir LEFT OUTER JOIN gerçekleştirerek başlayın ve ardından 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
Ve benzer şekilde, SAĞ HARİÇ BİR BİRLEŞTİRME 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 tutmayan bir birleştirme yapmanız gerekiyorsa (IOW, 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ı isimler
Anahtar sütunlar farklı şekilde adlandırılırsa (örneğin, left
vardır keyLeft
ve yerine vardır) , right
bu durumda aşağıdakilerin keyRight
yerine ve bağımsız değişken olarak key
belirtmeniz gerekir :left_on
right_on
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çınmak
Ü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ıyla (yani çıktısıyla left2.merge(right2, left_on='keyLeft', right_on='keyRight', how='inner')
) karşılaştırırsanız, keyLeft
eksik olduğunu fark edeceksiniz . Anahtar olarak hangi çerçevenin indeksinin ayarlandığına bağlı olarak hangi sütunun tutulacağını anlayabilirsiniz. Bu, örneğin bazı OUTER JOIN işlemi gerçekleştirirken önemli olabilir.
Yalnızca tek bir sütunu birleştirmek DataFrames
Örneğin, düşünün
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" (diğer sütunların hiçbiri olmadan) birleştirmeniz gerekiyorsa, genellikle birleştirmeden önce yalnızca sütunları alt küme yapabilirsiniz:
left.merge(right3[['key', 'newcol']], on='key')
key value newcol
0 B 0.400157 0
1 D 2.240893 1
LEFT OUTER JOIN 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
Bahsedildiğ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 adların farklı olması durumunda,
left.merge(right, left_on=['lkey1', 'lkey2'], right_on=['rkey1', 'rkey2'])
Diğer yararlı merge*
işlemler ve işlevler
Bir DataFrame'i dizindeki Seri ile birleştirme : Bu yanıta bakın .
Ayrıca
merge
,DataFrame.update
veDataFrame.combine_first
aynı zamanda birbirleriyle bir DataFrame güncellemek için bazı durumlarda kullanılmaktadır.pd.merge_ordered
sıralı JOIN'ler için kullanışlı bir işlevdir.pd.merge_asof
(okuyun: merge_asOf) yaklaşık birleşimler için kullanışlıdır .
Bu bölüm yalnızca en temel bilgileri kapsar ve yalnızca iştahınızı kabartmak 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.
Dizine dayalı * -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, dizinde bir 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 dizini üzerinde birleştirme, diğerinin sütun (lar) ı
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)
Veya 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ı sıra bir başka özlü seçenek daha var. DataFrame.join
Dizine katılmak için varsayılanları kullanabilirsiniz . DataFrame.join
varsayılan olarak 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
Aksi takdirde hata vereceğinden lsuffix
ve rsuffix
argümanlarını belirtmem gerektiğini unutmayın join
:
left.join(right)
ValueError: columns overlap but no suffix specified: Index(['value'], dtype='object')
Sütun isimleri aynı olduğu için. Farklı adlar verilseydi bu bir sorun olmazdı.
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ştirmeler için bir 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'
FULL OUTER JOIN'e 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'deki bu kanonik pd.concat
gönderiye bakın .
Genelleme: merge
birden çok DataFrame'i oluşturma
Çoğu zaman, birden çok DataFrame birleştirildiğinde durum ortaya çıkar. Naif olarak, bu merge
aramaları zincirleyerek yapılabilir :
df1.merge(df2, ...).merge(df3, ...)
Ancak bu, birçok DataFrame için hızla 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 yollu 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
join='inner'
TAM DIŞ BİRLEŞTİRME için atlayın . LEFT veya RIGHT OUTER birleşimleri belirtemeyeceğinizi unutmayın (bunlara ihtiyacınız varsa join
, aşağıda açıklananları kullanın ).
Yinelenen anahtarlarda çok yollu birleştirme
concat
hızlıdır, ancak eksiklikleri vardır. 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 (Unutmayın ki join
DataFrames indekslerinde birleştirilir; merge
başlık altında çağırır ve aksi belirtilmedikçe LEFT OUTER JOIN 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
Tamamlayıcı bir görsel görünümü pd.concat([df0, df1], kwargs)
. Bildirim, kwarg o axis=0
ya axis=1
'ın anlamı kadar kolay değildir df.mean()
yadf.apply(func)
Bu cevapta pratik bir pandas.concat
.
Aşağıdakileri DataFrames
aynı sütun adlarıyla dikkate alarak :
Preco2018 boyutuyla (8784, 5)
Preco 2019 beden ile (8760, 5)
Bunlar aynı sütun adlarına sahiptir.
Sen kullanarak bunları birleştirebilirsiniz pandas.concat
basitçe tarafından,
import pandas as pd
frames = [Preco2018, Preco2019]
df_merged = pd.concat(frames)
Aşağıdaki boyuta sahip bir DataFrame ile sonuçlanan (17544, 5)
Eğer görselleştirmek istersen, bu şekilde çalışır.
( Kaynak )