Pandalar Birleşiyor 101

Dec 06 2018
  • Pandalarla ( INNER| ( LEFT| RIGHT| FULL) OUTER) nasıl yapılır JOIN?
  • 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

696 cs95 Dec 06 2018 at 13:41

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 mergevejoin

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şilNaN , 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 leftve rightbunlara 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ı leftkullanılır ve içindeki eksik veriler rightNaN 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ı rightkullanılır ve içindeki 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 ç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 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

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, leftvardır keyLeftve yerine vardır) , rightbu durumda aşağıdakilerin keyRightyerine ve bağımsız değişken olarak keybelirtmeniz gerekir :left_onright_onon

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 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ıyla (yani çıktısıyla left2.merge(right2, left_on='keyLeft', right_on='keyRight', how='inner')) karşılaştırırsanız, keyLefteksik 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_onve right_onuygun 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

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, joinveconcat 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_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 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 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ı sıra bir başka özlü seçenek daha var. DataFrame.joinDizine katılmak için varsayılanları kullanabilirsiniz . DataFrame.joinvarsayı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 lsuffixve rsuffixargü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.concatgönderiye bakın .


Genelleme: mergebirden çok DataFrame'i oluşturma

Çoğu zaman, birden çok DataFrame birleştirildiğinde durum ortaya çıkar. Naif olarak, bu mergearamaları 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.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

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

concathı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, joinbenzersiz olmayan anahtarları işleyebildiği için kullanabiliriz (Unutmayın ki joinDataFrames indekslerinde birleştirilir; mergebaş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
62 eliu Apr 26 2019 at 06:43

Tamamlayıcı bir görsel görünümü pd.concat([df0, df1], kwargs). Bildirim, kwarg o axis=0ya axis=1'ın anlamı kadar kolay değildir df.mean()yadf.apply(func)


5 GonçaloPeres龚燿禄 Aug 10 2020 at 17:13

Bu cevapta pratik bir pandas.concat.

Aşağıdakileri DataFramesaynı 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.concatbasitç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 )