반응형

08-04. 객체병합 (merge)

DataFrame.merge(right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=False, suffixes=('_x', '_y'), copy=True, indicator=False, validate=None)

 

개요


merge메서드는 두 객체를 병합하는 메서드입니다. join과 비슷하지만 더 세부적인 설정이 가능한 메서드로,
인덱스-열 기준 병합도 가능하며, indicator인수를 통한 병합정보확인, validate를 통한 병합방식 확인등이 가능합니다.

 

사용법


left.merge(right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=False, suffixes=('_x', '_y'), copy=True, indicator=False, validate=None)
right : left와 함께 병합할 객체입니다.
how : 병합시 기준이 될 인덱스를 정하는 방식입니다. left는 기존객체, right는 병합할 객체, inner은 두 객체의 인덱스의 교집합, outer은 두 객체의 인덱스의 합집합, cross는 행렬곱 입니다.
on : 열 기준 병합시 기준으로할 열의 이름이 양측이 동일하다면, on인수에 입력함으로써 기준 열을 정할 수 있습니다.
left_on / right_on : 열기준 병합 시 기준으로 할 열의 양측 이름이 다르다면, 각각 어떤 열을 기준으로 할지 정해줍니다.
열의 이름을 입력하면 됩니다.
left_index / right_index : 인덱스 기준 병합 시 True로 하면 해당 객체의 인덱스가 병합 기준이됩니다.

※ 즉 left_on을 입력하고 right_index를 True로 한다면 열-인덱스 기준 병합도 가능합니다.

sort : 병합 후 인덱스의 사전적 정렬 여부입니다. join메서드와 기능이 동일하므로 참고 바랍니다.
suffixes : 병합할 객체들간 이름이 중복되는 열이 있다면, 해당 열에 붙일 접미사를 정합니다.
기본적으로 join메서드의 lsuffix / rsuffix와 기능이 동일하지만, suffixes인수는 튜플로 두 값을
한번에 입력한다는 차이가 있습니다.
copy : 사본을 생성할지 여부입니다.
indicator : True로 할경우 병합이 완료된 객체에 추가로 열을 하나 생성하여 병합 정보를 출력합니다.
validate : {'1:1' / '1:m' / 'm:1' / 'm:m'} 병합 방식에 맞는지 확인할 수 있습니다. 만약 validate에 입력한 병합방식과, 실제 병합 방식이 다를경우 오류가 발생됩니다.
예를들어, validate="1:m"으로 입력하였는데, 실제로 m:1 병합방식일 경우 오류가 발생됩니다.

 

예시


기본 사용법
인수가 많은만큼 예시가 많기 때문에, 설명할때마다 샘플 객체를 만들어서 설명 진행하겠습니다.

열 기준으로 병합 (left_on / right_on)
left_on / right_on에 열 이름을 입력하므로서 열 기준으로 병합이 가능합니다.
먼저 객체 2개를 만들어 보겠습니다.

df1 = pd.DataFrame({'IDX1':['a','b','c','a'],'VAL':[1,2,3,4]})
print(df1)
>>
  IDX1  VAL
0    a    1
1    b    2
2    c    3
3    a    4
df2 = pd.DataFrame({'IDX2':['a','c','d'],'VAL':[5,6,7]})
print(df2)
>>
  IDX2  VAL
0    a    5
1    c    6
2    d    7

df1에서는 IDX1을, df2에서는 IDX2를 기준으로 하여 두 객체를 병합하겠습니다.
IDX1과 IDX2의 값을 매칭하여 병합된 후 이름이 같은 VAL열에 대해서는 _x와 _y가 붙었습니다.

print(df1.merge(df2, left_on='IDX1',right_on='IDX2'))
>>
  IDX1  VAL_x IDX2  VAL_y
0    a      1    a      5
1    a      4    a      5
2    c      3    c      6


suffixes를 통한 동명인 열 구분
suffixes ('_left', '_right')를 입력하므로써 열 이름에 _left, _right를 붙일 수 있습니다.

print(df1.merge(df2, left_on='IDX1',right_on='IDX2',suffixes=('_left','_right')))
>>
  IDX1  VAL_left IDX2  VAL_right
0    a         1    a          5
1    a         4    a          5
2    c         3    c          6


인덱스 기준으로 병합(left_index / right_index)
left_index / right_index를 통해 인덱스 기준으로 두 객체를 병합할 수 있습니다.
먼저 병합할 두 객체를 만들어보겠습니다.

df3 = pd.DataFrame({'VAL1':[1,2,3]},index=['row1','row2','row3'])
print(df3)
>>
      VAL1
row1     1
row2     2
row3     3
df4 = pd.DataFrame({'VAL2':[4,5,6]},index=['row2','row3','row4'])
print(df4)
>>
      VAL2
row2     4
row3     5
row4     6

left_index right_index True로 입력하여 두 객체 모두 인덱스를 기준으로 병합할 수 있습니다.

print(df3.merge(df4, left_index=True,right_index=True))
>>
      VAL1  VAL2
row2     2     4
row3     3     5


열과 인덱스를 혼합하여 병합하기
left_on / right_on  left_index / right_index를 이용하여 양쪽의 기준을 설정해줌으로서, 인덱스와 열의 혼합 병합도 가능합니다.
예시를 위해서 새 객체 두개를 만들어보겠습니다.
df5는 인덱스를, df6은 열을 기준으로 하겠습니다.

df5 = pd.DataFrame({'VAL1':[1,2,3]},index=['row1','row2','row3'])
print(df5)
>>
      VAL1
row1     1
row2     2
row3     3
df6 = pd.DataFrame({'IDX':['row2','row3','row4'],'VAL2':[4,5,6]})
print(df6)
>>
    IDX  VAL2
0  row2     4
1  row3     5
2  row4     6

이제 left_index True로하여 인덱스를 기준으로하고 right_on IDX로 하여 열 기준으로 병합하겠습니다.

print(df5.merge(df6, left_index=True,right_on='IDX'))
>>
   VAL1   IDX  VAL2
0     2  row2     4
1     3  row3     5


how 인수의 사용
how인수를 사용하여 병합된 객체의 인덱스의 기준을 정할 수 있습니다.
먼저 예시에 이용될 두 객체를 만들어 보겠습니다.

df7 = pd.DataFrame({'IDX':['a','b','c','a'],'VAL':[1,2,3,4]})
print(df7)
>>
  IDX  VAL
0   a    1
1   b    2
2   c    3
3   a    4
df8 = pd.DataFrame({'IDX':['a','c','d'],'VAL':[5,6,7]})
print(df8)
>>
  IDX  VAL
0   a    5
1   c    6
2   d    7

how=left인 경우 왼쪽 객체의 인덱스를 기준으로 합니다.

print(df7.merge(df8,how='left',on='IDX'))
>>
  IDX  VAL_x  VAL_y
0   a      1    5.0
1   b      2    NaN
2   c      3    6.0
3   a      4    5.0

how=right인 경우 오른쪽 객체의 인덱스를 기준으로 합니다.

print(df7.merge(df8,how='right',on='IDX'))
>>
  IDX  VAL_x  VAL_y
0   a    1.0      5
1   a    4.0      5
2   c    3.0      6
3   d    NaN      7

how=inner인 경우 양쪽 객체 모두가 공통으로 갖는 인덱스를 기준으로 합니다.(교집합)

print(df7.merge(df8,how='inner',on='IDX'))
>>
  IDX  VAL_x  VAL_y
0   a      1      5
1   a      4      5
2   c      3      6

how=outer인 경우 양쪽 객체의 인덱스 모두를 기준으로 합니다.(합집합)

print(df7.merge(df8,how='outer',on='IDX'))
>>
  IDX  VAL_x  VAL_y
0   a    1.0    5.0
1   a    4.0    5.0
2   b    2.0    NaN
3   c    3.0    6.0
4   d    NaN    7.0

※cross에 대해서는 뒤에 후술하겠습니다.

indicator인수를 통한 병합 정보 출력
indicator인수를 True로 할 경우 마지막 열에 _merge열을 추가하여 병합 정보를 출력합니다.

print(df7.merge(df8,how='outer',on='IDX',indicator=True))
>>
  IDX  VAL_x  VAL_y      _merge
0   a    1.0    5.0        both
1   a    4.0    5.0        both
2   b    2.0    NaN   left_only
3   c    3.0    6.0        both
4   d    NaN    7.0  right_only


validate를 통한 병합방식 검증
validate인수에 값을 입력하여 해당 병합방식이 맞는지 검증이 가능합니다. 병합 방식이 다를경우 오류를 출력합니다.
1:m인지 검증

print(df7.merge(df8,how='outer',on='IDX',validate='1:m'))
>>
오류발생
pandas.errors.MergeError: Merge keys are not unique in left dataset; not a one-to-many merge

m:1인지 검증. 병합 방식이 m:1이 맞기 때문에 결과값을 출력합니다.

print(df7.merge(df8,how='outer',on='IDX',validate='m:1'))
>>
  IDX  VAL_x  VAL_y
0   a    1.0    5.0
1   a    4.0    5.0
2   b    2.0    NaN
3   c    3.0    6.0
4   d    NaN    7.0


how인수에 cross를 적용하는 경우
how인수중 cross는 행렬의 곱집합을 의미합니다. 단순히 말하면 행렬의 모든 경우의수를 출력합니다.
예시를 위해 두 객체를 생성해보겠습니다.

df9 = pd.DataFrame({'IDX1':['a','b']})
print(df9)
>>
  IDX1
0    a
1    b
df10 = pd.DataFrame({'IDX2':['c','d']})
print(df10)
>>
  IDX2
0    c
1    d

이제 how인수에 cross를 입력하므로써 두 객체의 행렬곱을 출력하겠습니다.

print(df9.merge(df10,how='cross'))
>>
  IDX1 IDX2
0    a    c
1    a    d
2    b    c
3    b    d
반응형

+ 최근 글