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
'파이썬완전정복-Pandas DataFrame > 08. 결합' 카테고리의 다른 글
Pandas DataFrame 08-06. 업데이트 (update) (0) | 2022.01.23 |
---|---|
Pandas DataFrame 08-05. 객체 병합_결측제어 가능 (align) (0) | 2022.01.23 |
Pandas DataFrame 08-03. 인덱스기준 병합 (join) (0) | 2022.01.23 |
Pandas DataFrame 08-02. 다른 객체로 결측치 덮어쓰기 (combine_first) (0) | 2022.01.23 |
Pandas DataFrame 08-01. 함수를 이용한 열 단위 결합 (combine) (0) | 2022.01.22 |