ylabel - set_title python




熊貓合併101 (2)

這篇文章旨在為讀者提供關於SQL風格的大熊貓合併,如何使用以及何時不使用它的入門知識。

特別是,這篇文章將通過以下內容:

  • 基礎知識 - 連接類型(LEFT,RIGHT,OUTER,INNER)

    • 合併不同的列名稱
    • 避免輸出中出現重複的合併鍵列
  • 在不同條件下與指數合併
    • 有效地使用你的命名索引
    • 合併鍵作為另一個的列和列的索引
  • Multiway合併列和索引(唯一和非唯一)
  • mergejoin 顯著替代方案

這篇文章不會經歷的內容:

  • 與績效相關的討論和時間安排(目前)。 在合適的情況下,最值得注意的是提到更好的替代品。
  • 處理後綴,刪除額外的列,重命名輸出和其他特定用例。 還有其他(閱讀:更好)帖子處理,所以搞清楚!

注意
除非另有說明,否則大多數示例默認為INNER JOIN操作,同時演示各種功能。

此外,可以復制和復制此處的所有DataFrame,以便您可以使用它們。 另外,請參閱 此文章 ,了解如何從剪貼板中讀取DataFrame。

最後,JOIN操作的所有可視化表示都是使用Google Drawings手繪的。 來自 here 靈感。

足夠的談話,只是告訴我如何使用 merge

建立

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

為簡單起見,鍵列具有相同的名稱(暫時)。

INNER JOIN 表示為

注意
這一點以及即將出現的數字都遵循這一慣例:

  • blue 表示合併結果中存在的行
  • 紅色 表示從結果中排除的行(即刪除)
  • 綠色 表示在結果中用NaN替換的缺失值

要執行INNER JOIN,請調用 pd.merge 指定左側DataFrame,右側DataFrame和連接鍵。

pd.merge(left, right, on='key')

  key   value_x   value_y
0   B  0.400157  1.867558
1   D  2.240893 -0.977278

這僅返回來自 leftright 行,這些行共享一個公共密鑰(在本例中為“B”和“D”)。

在更新版本的pandas(v0.21左右)中, merge 現在是一階函數,因此您可以調用 DataFrame.merge

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

LEFT OUTER JOIN 或LEFT JOIN表示為

這可以通過指定how''left 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

仔細注意NaNs的位置。 如果指定 how='left' ,則僅使用 left 鍵, left 的缺失數據將替換為NaN。

同樣地,對於一個 正確的外部聯接 ,或者正確的聯合......

...指定 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

這裡,使用 right 鍵, left 缺失數據被NaN替換。

最後,對於 FULL OUTER JOIN ,給出

指定 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

這將使用兩個幀中的鍵,並插入NaN以用於兩者中的缺失行。

該文檔很好地總結了這些不同的合併:

其他聯接 - 左排除,右排除和全排除/反聯動

如果你需要 LEFT-排除JOIN RIGHT-排除JOIN 分兩步。

對於LEFT-排除JOIN,表示為

首先執行LEFT OUTER JOIN,然後過濾(不包括!)僅來自 left 行,

(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

哪裡,

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

同樣,對於正確的排除加入,

(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

最後,如果您需要進行只保留左側或右側鍵的合併,而不是兩者都保持鍵(IOW,執行 ANTI-JOIN ),

你可以用類似的方式做到這一點 -

(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

鍵列的不同名稱

如果鍵列的名稱不同 - 例如, left 具有 keyLeft ,而 right 具有 keyRight 而不是 keyRight 那麼您必須指定 left_onright_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

避免輸出中的重複鍵列

當從 left 合併 keyLeft 和從 right 合併 keyLeft ,如果您只想要輸出中的 keyLeftkeyRight (但不是兩者),則可以 keyRight 索引設置為預備步驟。

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

將此與之前命令的輸出(左邊是left2.merge的輸出 left2.merge(right2, left_on='keyLeft', right_on='keyRight', how='inner') )進行 keyLeft ,你會發現 keyLeft 缺失了。 您可以根據將哪個幀的索引設置為鍵來確定要保留的列。 例如,執行某些OUTER JOIN操作時,這可能很重要。

僅合併其中一個 DataFrames 的單個列

例如,考慮一下

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

如果您只需要合併“new_val”(沒有任何其他列),通常只需在合併之前對列進行子集化:

left.merge(right3[['key', 'newcol']], on='key')

  key     value  newcol
0   B  0.400157       0
1   D  2.240893       1

如果您正在進行LEFT OUTER JOIN,那麼性能更高的解決方案將涉及 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

如上所述,這類似於,但速度快於

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

合併多列

要連接多個列,請為 on (或 left_onright_on ,視情況而定)指定一個列表。

left.merge(right, on=['key1', 'key2'] ...)

或者,如果名稱不同,

left.merge(right, left_on=['lkey1', 'lkey2'], right_on=['rkey1', 'rkey2'])

其他有用的 merge* 操作和函數

本節僅介紹非常基本的內容,旨在滿足您的胃口。 有關更多示例和案例,請參閱 有關 mergejoinconcat 文檔 以及函數規範的鏈接。

基於索引的* -JOIN(+索引列 merge

建立

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

通常,索引上的合併將如下所示:

left.merge(right, left_index=True, right_index=True)


         value_x   value_y
idxkey                    
B      -0.402655  0.543843
D      -0.524349  0.013135

支持索引名稱

如果您的索引已命名,則v0.23用戶還可以將級別名稱指定為 on (或者根據需要指定 left_onright_on )。

left.merge(right, on='idxkey')

         value_x   value_y
idxkey                    
B      -0.402655  0.543843
D      -0.524349  0.013135

合併另一個的一個,一個列的索引

可以(並且非常簡單)使用一個索引和另一個索引來執行合併。 例如,

left.merge(right, left_on='key1', right_index=True)

反之亦然( right_on=...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

在這種特殊情況下, left 的索引被命名,因此您也可以將索引名稱與 left_on 一起 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
除此之外,還有另一種簡潔的選擇。 您可以使用默認為索引連接的 DataFrame.join 。 默認情況下, DataFrame.join 執行LEFT OUTER JOIN,因此這裡有必要 how='inner'

left.join(right, how='inner', lsuffix='_x', rsuffix='_y')

         value_x   value_y
idxkey                    
B      -0.402655  0.543843
D      -0.524349  0.013135

請注意,我需要指定 lsuffixrsuffix 參數,因為 join 會以其他方式輸出錯誤:

left.join(right)
ValueError: columns overlap but no suffix specified: Index(['value'], dtype='object')

由於列名相同。 如果它們的名稱不同,這不會成為問題。

left.rename(columns={'value':'leftvalue'}).join(right, how='inner')

        leftvalue     value
idxkey                     
B       -0.402655  0.543843
D       -0.524349  0.013135

pd.concat
最後,作為基於索引的連接的替代方法,您可以使用 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

如果需要FULL OUTER JOIN(默認值),則省略 join='inner'

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

有關更多信息,請參閱 pd.concat 在pd.concat上 pd.concat 的這個規範帖子

概括: merge 多個DataFrame

通常情況下,當要將多個DataFrame合併在一起時會出現這種情況。 天真地,這可以通過鏈接 merge 調用來完成:

df1.merge(df2, ...).merge(df3, ...)

但是,對於許多DataFrame而言,這很快就會失控。 此外,可能需要概括未知數量的DataFrame。

這裡我介紹 pd.concat 用於 唯一 鍵上的多路連接的 DataFrame.join ,以及用於 非唯一 鍵上的多路連接的 DataFrame.join 。 首先,設置。

# 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]

Multiway合併唯一鍵(或索引)

如果您的密鑰(此處,密鑰可以是列或索引)是唯一的,那麼您可以使用 pd.concat 。 請注意, pd.concat 在索引上連接DataFrame

# 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' 進行FULL OUTER JOIN。 請注意,您不能指定LEFT或RIGHT OUTER連接(如果需要這些連接,請使用 join ,如下所述)。

Multiway合併密鑰與重複

concat 很快,但有它的缺點。 它無法處理重複。

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)

在這種情況下,我們可以使用 join 因為它可以處理非唯一鍵(請注意, join 在其索引上連接DataFrames;它在引擎蓋下調用 merge 並執行LEFT OUTER JOIN,除非另有指定)。

# 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
  • 如何使用pandas執行( LEFT | RIGHT | FULL )( INNER | OUTER )連接?
  • 合併後如何為缺失的行添加NaN?
  • 合併後如何擺脫NaN?
  • 我可以合併索引嗎?
  • 與熊貓交叉加入?
  • 如何合併多個DataFrame?
  • mergejoinconcatupdate ? 誰? 什麼? 為什麼?!

... 和更多。 我已經看到了這些反復出現的問題,詢問了pandas合併功能的各個方面。 今天關於合併及其各種用例的大部分信息在數十個措辭嚴厲,不可搜索的帖子中都是分散的。 這裡的目的是為後代整理一些更重要的觀點。

這個QnA應該是關於常見熊貓習語的一系列有用的用戶指南的下一部分(參見 關於轉動的 這篇文章 ,以及 關於連接的這篇文章 ,我將在稍後介紹)。

請注意,這篇文章 並不是 documentation 的替代品,所以請閱讀它! 一些例子來自那裡。


pd.concat([df0, df1], kwargs) 補充視覺視圖。 請注意,kwarg axis=0axis=1 的含義不如 df.mean()df.apply(func) 那麼直觀





merge