팬더 병합 101


362
  • 팬더와 ( LEFT| RIGHT| FULL) ( INNER| OUTER) 조인 을 수행하는 방법은 무엇입니까?
  • 병합 후 누락 된 행에 NaN을 추가하려면 어떻게합니까?
  • 병합 후 NaN을 제거하려면 어떻게해야합니까?
  • 인덱스를 병합 할 수 있습니까?
  • 팬더와 크로스 조인?
  • 여러 DataFrame을 병합하려면 어떻게합니까?
  • merge? join? concat? update? WHO? 뭐? 왜?!

... 그리고 더. 팬더 병합 기능의 다양한 측면에 대해 묻는 반복되는 질문을 보았습니다. 오늘날의 병합 및 다양한 사용 사례에 관한 대부분의 정보는 수십 가지의 나쁜 말로 표현할 수없는 게시물에 걸쳐 있습니다. 여기서 목표는 후손에 대한 더 중요한 요점을 정리하는 것입니다.

이 QnA는 일반적인 팬더 관용구에 대한 일련의 유용한 사용자 안내서의 다음 편입니다. ( 이 글은 피벗대한 게시물과 연결 에 대한 게시물을 참조하십시오 .

이 게시물이되고 있습니다 하지 대체 될 운명 문서 , 그래서 그뿐만 아니라 읽으십시오를! 일부 예제는 거기에서 가져옵니다.

답변:


517

이 글은 독자들에게 판다와의 SQL 맛 병합, 사용법, 사용하지 않을 때의 입문서를 제공하는 것을 목표로합니다.

특히이 게시물의 내용은 다음과 같습니다.

  • 기본 사항-조인 유형 (LEFT, RIGHT, OUTER, INNER)

    • 다른 열 이름과 병합
    • 출력에서 중복 병합 키 열 피하기
  • 다른 조건에서 인덱스와 병합
    • 효과적으로 명명 된 인덱스를 사용하여
    • 하나의 인덱스와 다른 열의 병합 키
  • 열과 인덱스에서 다 방향 병합 (고유 및 비 고유)
  • 에 주목할만한 대안 mergejoin

이 게시물에서 다루지 않을 내용 :

  • 성능 관련 토론 및 타이밍 (현재) 적절한 경우 더 나은 대안에 대한 언급이 가장 눈에.니다.
  • 접미사 처리, 추가 열 제거, 출력 이름 바꾸기 및 기타 특정 사용 사례. 그것을 다루는 다른 (읽기 : 더 나은) 게시물이 있으므로 알아 내십시오!

참고
달리 지정하지 않는 한, 대부분의 예제는 다양한 기능을 보여 주면서 INNER JOIN 작업으로 기본 설정됩니다.

또한 여기의 모든 DataFrame을 복사 및 복제하여 재생할 수 있습니다. 또한 클립 보드에서 DataFrames를 읽는 방법에 대한 이 게시물 을 참조하십시오 .

마지막으로 JOIN 작업의 모든 시각적 표현은 Google 드로잉을 사용하여 손으로 그린 ​​것입니다. 여기 에서 영감을 얻 습니다 .

충분한 대화, 사용 방법을 보여주세요 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 에 의해 표현된다

참고
이것은 다음 수치와 함께이 규칙을 따릅니다.

  • 파란색 은 병합 결과에있는 행을 나타냅니다.
  • 빨간색 은 결과에서 제외 된 행을 나타냅니다 (즉, 제거됨)
  • 녹색 은 결과에서 NaN으로 대체 된 결 측값을 나타냅니다.

INNER JOIN을 수행하려면 merge오른쪽 DataFrame과 조인 키 (최소한)를 인수로 지정하여 왼쪽 DataFrame을 호출 하십시오.

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

이 수익률 만 행 leftright공통 (이 예에서는, "B"와 "D) 키를 공유 할 수 있습니다.

LEFT OUTER는 가입 또는 왼쪽으로 표시 조인

이를 지정하여 수행 할 수 있습니다 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의 배치에주의하십시오. 을 지정하면의 how='left'키만 left사용되며 누락 된 데이터 right는 NaN으로 바뀝니다.

마찬가지로 RIGHT OUTER JOIN 또는 RIGHT JOIN의 경우 ...

... 특정 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은 두 행에서 누락 된 행에 삽입됩니다.

문서는 이러한 다양한 병합을 잘 요약합니다.

여기에 이미지 설명을 입력하십시오

기타 JOIN-왼쪽 제외, 오른쪽 제외 및 전체 제외 / ANTI 가입

두 단계로 왼쪽 제외 조인오른쪽 제외 조인 이 필요한 경우 .

왼쪽 제외 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

키 열의 다른 이름

키 열의 이름이 다른 경우 (예 : lefthas keyLeftrighthas keyRight대신 key) 다음 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

출력에서 중복 키 열 피하기

keyLeftfrom leftkeyRightfrom을 병합 할 때 출력에서 또는 right둘 중 하나만 원하는 경우 색인을 예비 단계로 설정하여 시작할 수 있습니다.keyLeftkeyRight

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(right2, left_on='keyLeft', right_on='keyRight', how='inner')) 과 대조하면 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*작업 및 기능

이 섹션은 매우 기본적인 내용만을 다루며 식욕을 자극하기 위해 고안되었습니다. 더 많은 예제와 사례를 들어, 참조 에 대한 문서를 merge, join그리고concat 뿐만 아니라 기능 사양에 대한 링크로.


인덱스 기반 * -JOIN (+ 인덱스 열 merges)

설정

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.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왼쪽 외부 가입은 기본적으로 수행되므로 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

그렇지 않으면 오류가 발생 하므로 lsuffixand rsuffix인수 를 지정해야합니다 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

join='inner'FULL OUTER JOIN (기본값)이 필요한 경우 생략 하십시오.

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

자세한 내용 은 @piRSquared의 정식 게시물을pd.concat 참조하십시오 .


일반화 : merge다중 DataFrame

종종 여러 DataFrame을 병합 할 때 상황이 발생합니다. 순진하게 이것은 merge호출 을 연결하여 수행 할 수 있습니다 .

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

그러나 이것은 많은 DataFrames에서 빨리 사라집니다. 또한 알려지지 않은 수의 DataFrame에 대해 일반화해야 할 수도 있습니다.

여기에서는 고유 키의 다 방향 조인 과 고유하지 않은 키의 pd.concat다 방향 조인에 대해 소개 합니다. 먼저 설정입니다.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]

고유 키 (또는 인덱스)에서 다자간 병합

키 (여기서는 키가 열 또는 인덱스 일 수 있음)가 고유 한 경우을 사용할 수 있습니다 pd.concat. pd.concat인덱스에서 DataFrames조인합니다 .

# 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'전체 외부 참여를 생략하십시오 . LEFT 또는 RIGHT OUTER 조인을 지정할 수 없습니다 (필요한 경우 join아래 설명 참조).

중복 키가있는 멀티 웨이 병합

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

49

에 대한 보충적인 시각 pd.concat([df0, df1], kwargs). 공지 사항, kwarg 것을 axis=0또는 axis=1'의 의미처럼 직관적으로하지 않습니다 df.mean()또는df.apply(func)


pd.concat ([df0, df1])


9
이것은 좋은 다이어그램입니다. 어떻게 생산했는지 물어봐도 될까요?
cs95

6
Google 문서의 내장 'insert ==> drawing ... ==> new'(2019 년 5 월 기준) 그러나 분명히하기 위해이 그림에 Google 문서를 사용한 유일한 이유는 메모가 Google 문서에 저장되어 있기 때문에 Google 문서 자체에서 빠르게 수정할 수있는 사진을 원하기 때문입니다. 실제로 지금 언급했듯이 Google 문서의 그리기 도구는 매우 깔끔합니다.
eliu

와, 대단하다. SQL 세계에서 나오는 테이블 구조는 항상 고정되어 있기 때문에 "수직"조인은 제 조인이 아닙니다. 지금도 팬더가 통합해야한다고 생각 concat하고 merge방향 매개 변수 인 상태 horizontalvertical.
Ufos

2
@Ufos 정확히 무엇을하는 것이 아닌가 axis=1하고는 axis=0무엇입니까?
cs95

2
예, 지금 거기 mergeconcat및 축과 뭐든간에. 그러나 @eliu에서 알 수 있듯이 "왼쪽", "오른쪽", "가로"또는 "세로"와 병합 개념은 모두 같습니다 . 나는 개인적으로 어떤 "축"이 무엇인지 0, 어느 것이 무엇인지 기억해야 할 때마다 문서를 조사해야합니다 1.
Ufos
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.