[Python Pandas] 데이터프레임을 결합하는 함수 merge 이해하기

이번 포스팅에서는 Python Pandas 라이브러리에서 제공하는 데이터프레임을 결합하는 함수 merge 에 대해서 알아 보겠습니다.
데이터프레임의 결합은 데이터 분석을 위한 전처리 시 기본이며, 매우 중요합니다.
기본적인 문법만 잘 인지하고 있으면, 실제 데이터 분석에서도 어렵지 않게 사용할 수 있을 것으로 생각합니다.

데이터프레임을 결합하는 함수 merge 구문

merge 함수에서 Series 개체는 하나의 열을 가지는 DataFrame으로 처리합니다. 열이나 인덱스를 기준으로 결합을 수행합니다.
열과 열을 조인하는 경우 DataFrame 의 인덱스는 무시됩니다.

그렇지 않고 인덱스와 인덱스 혹은 열의 인덱스를 이용하여 결합하는 경우 인덱스가 전달됩니다.
교차 병합을 수행할 때 병합할 열 지정은 허용되지 않습니다.

merget 함수의 기본 구문은 아래와 같습니다.


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 = None
indicator = False
validate = None )


반환값은 병합된 DataFrame입니다.



데이터프레임을 결합하는 함수 merge 인수


  • right : DataFrame or named Series
    • 병합할 개체(DataFrame or named Series)를 나타냅니다.


  • how : {‘left’, ‘right’, ‘outer’, ‘inner’, ‘cross’}, default ‘inner’
    • 수행할 병합 방법을 나타냅니다.
    • left: SQL 구문에서 left outer join과 유사하게 왼쪽 데이터프레임의 key를 기준으로 결합합니다.
    • right: SQL 구문에서 right outer join과 유사하게 오른쪽 데이터프레임의 key를 기준으로 결합합니다.
    • outer: SQL 구문에서 full outer join과 유사하게 두 데이터프레임의 모든 key를 고려하여 결합합니다.
    • inner: SQL 구문에서 inner join과 유사하게 두 데이터프레임에 모두 존재하는 key 를 고려하여 결합합니다.
    • cross: 두 데이터프레임 모두에서 데카르트 곱을 생성하여 결합하고, 왼쪽 키의 순서를 유지합니다.


  • on : label or list
    • 결합할 열 또는 인덱스 수준의 이름을 나타냅니다. 해당 key는 두 데이터프레임에 모두 존재해야 합니다.
      on이 None이고 인덱스를 결합하지 않는 경우 기본값은 두 DataFrame의 열 교차입니다.


  • left_on : label or list, or array-like
    • 왼쪽 데이터프레임에서 결합할 열 또는 인덱스 수준 이름입니다. 왼쪽 DataFrame 길이의 배열 또는 배열 리스트일 수도 있습니다. 이러한 배열은 열인 것처럼 처리됩니다.


  • right_on : label or list, or array-like
    • 오른쪽 DataFrame에서 결합할 열 또는 인덱스 수준 이름입니다. 오른쪽 DataFrame 길이의 배열 또는 배열 리스트일 수도 있습니다. 이러한 배열은 열인 것처럼 처리됩니다.


  • left_index : bool, default False
    • 왼쪽 DataFrame의 인덱스를 결합 key로 사용합니다. MultiIndex인 경우 다른 DataFrame의 key 수(인덱스 또는 열 수)는 레벨 수와 일치해야 합니다.


  • right_index : bool, default False
    • 오른쪽 DataFrame의 인덱스를 결합 key로 사용합니다. 주의사항은 left_index와 동일합니다.


  • sort : bool, default False
    • 결과 DataFrame에서 결합 key를 사전순으로 정렬합니다. False인 경우 결합 key의 순서는 결합 유형(how 인수)에 따라 달라집니다.


  • suffixes : list-like, default is (“_x”, “_y”)
    • 왼쪽 데이터프레임과 오른쪽 데이터프레임에서 각각 겹치는 열 이름에 대해서 결합 후 추가할 접미사를 나타냅니다.
      길이가 2인 문자열 시퀀스입니다.
      왼쪽 데이터프레임과 오른쪽 데이터프레임에서의 열 이름이 접미사 없이 그대로 유지되어야 함을 나타내려면 문자열 대신 None 값을 전달합니다. 값 중 하나 이상이 None이 아니어야 합니다.


  • copy : bool, default True
    • False는 가능하면 사용하지 마세요.


  • indicator : bool or str, default False
    • True인 경우 각 행의 소스에 대한 정보와 함께 “_merge”라는 열을 출력 DataFrame에 추가합니다. 문자열 인수를 제공하여 열에 다른 이름을 지정할 수 있습니다.
      열에는 결합 key가 왼쪽 DataFrame에만 나타나는 관측치의 경우 “left_only” 값, 오른쪽 DataFrame에만 결합 key가 나타나는 관측치의 경우 “right_only”, 관측치가 두 DataFrame에서 모두 발견되는 경우, “both” 값을 갖는 범주형 유형이 있습니다.


  • validate : str, optional
    • 지정할 경우 결합이 지정된 유형인지 확인합니다.
    • “one_to_one” or “1:1” : 왼쪽 및 오른쪽 데이터프레임 모두에서 결합 key가 고유한지 확인합니다.
    • “one_to_many” or “1:m” :  왼쪽 데이터프레임에서 병합 키가 고유한지 확인합니다.
    • “many_to_one” or “m:1” : 결합 key가 오른쪽 데이터프레임에서 고유한지 확인합니다.
    • “many_to_many” or “m:m” : 허용되기는 하지만, 검사를 받지는 않습니다.


데이터프레임을 결합하는 함수 merge 사용 예시

데이터 결합 시 주로 사용하는 인수를 기준으로 데이터프레임을 결합하는 함수 merget 의 사용 예시를 알아 보겠습니다.

import pandas as pd

tempData1 = pd.DataFrame({'lkey': ['foo', 'bar', 'baz', 'foo', 'zoo'],
                          'value': [1, 2, 3, 5, 7]})

tempData2 = pd.DataFrame({'rkey': ['foo', 'bar', 'baz', 'foo', 'exc'],
                          'value': [1, 2, 3, 5, 9]})
tempData1
--------------------------
	lkey	value
0	foo	    1
1	bar	    2
2	baz	    3
3	foo	    5
4	zoo	    7


tempData2
--------------------------
	rkey	value
0	foo	    1
1	bar	    2
2	baz	    3
3	foo	    5
4	exc	    9


left outer join 형식의 데이터 결합

mergeTempData = tempData1.merge(right = tempData2, how = 'left', left_on = 'lkey', right_on = 'rkey')
mergeTempData 
------------------------------------------
	lkey	value_x	rkey	value_y
0	foo	    1	    foo	    1.0
1	foo	    1	    foo	    5.0
2	bar	    2	    bar	    2.0
3	baz	    3    	baz	    3.0
4	foo	    5	    foo	    1.0
5	foo	    5	    foo	    5.0
6	zoo	    7	    NaN	    NaN

tempData1 을 기준으로 tempData2를 left outer join (how = ‘left’)방식으로 결합합니다.
결합 key의 값 중에서 ‘zoo’은 tempData2에 존재하지 않기 때문에 rkey 열과 value_y 열의 값은 NaN으로 표시됩니다.

두 데이터프레임의 결합 key가 다르기 때문에, left_on 과 right_on 인수를 사용하였고,
value 열은 두 데이터프레임에 모두 존재하기 때문에 이를 구별하기 위해 _x 와 _y가 기본값으로 추가되었습니다.

기본값 이외에 별도 명칭을 부여하려면 어떻게 하면 될까요? suffixes 인수를 사용하면 됩니다.

mergeTempData = tempData1.merge(right = tempData2, how = 'left', left_on = 'lkey', right_on = 'rkey', suffixes = ['_left','_right'])
mergeTempData 
--------------------------------------------
	lkey	value_left	rkey	value_right
0	foo	    1	        foo	    1.0
1	foo	    1	        foo	    5.0
2	bar	    2	        bar	    2.0
3	baz	    3    	    baz	    3.0
4	foo	    5	        foo	    1.0
5	foo	    5	        foo	    5.0
6	zoo	    7	        NaN	    NaN

value_x 와 value_y 열 이름이 value_left 와 value_right 로 변경되었습니다.

DataFrames tempData1과 tempData2를 결합할 때, 겹치는 열이 있으면 에러가 발생합니다.

mergeTempData = tempData1.merge(right = tempData2, how = 'left', left_on = 'lkey', right_on = 'rkey', suffixes = [False, False])
mergeTempData 
------------------------------------------------------------------------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[11], line 1
----> 1 mergeTempData = tempData1.merge(right = tempData2, how = 'left', left_on = 'lkey', right_on = 'rkey', suffixes = [False, False])

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


right outer join 형식의 데이터 결합

mergeTempData = tempData1.merge(right = tempData2, how = 'right', left_on = 'lkey', right_on = 'rkey', suffixes = ['_left','_right'])
mergeTempData
------------------------------------------------------------------
	lkey	value_left	rkey	value_right
0	foo	    1.0	        foo	    1
1	foo	    5.0	        foo	    1
2	bar	    2.0	        bar	    2
3	baz	    3.0	        baz	    3
4	foo	    1.0	        foo	    5
5	foo	    5.0	        foo	    5
6	NaN	    NaN	        exc	    9

tempData1 을 기준으로 tempData2를 right outer join (how = ‘right’)방식으로 결합합니다.
결합 key의 값 중에서 ‘exc’은 tempData1에 존재하지 않기 때문에 lkey 열과 value_left 열의 값은 NaN으로 표시됩니다.


full join 형식의 데이터 결합

mergeTempData = tempData1.merge(right = tempData2, how = 'outer', left_on = 'lkey', right_on = 'rkey', suffixes = ['_left','_right'])
mergeTempData
-----------------------------------------------------
        lkey	value_left	rkey	value_right
0	    foo	    1.0	        foo	    1.0
1	    foo	    1.0	        foo	    5.0
2	    foo	    5.0	        foo	    1.0
3	    foo	    5.0	        foo	    5.0
4	    bar	    2.0	        bar	    2.0
5	    baz	    3.0	        baz	    3.0
6	    zoo	    7.0	        NaN	    NaN
7	    NaN	    NaN	        exc	    9.0

tempData1와 tempData2를 full join (how = ‘outer’)방식으로 결합합니다.
tempData1와 tempData2의 모든 결합 key를 고려하여 데이터를 결합합니다.

결합 key의 값 중에서 ‘zoo’은 tempData2에 존재하지 않기 때문에 rkey 열과 value_y 열의 값은 NaN으로 표시되는 반면,
‘exc’은 tempData1에 존재하지 않기 때문에 lkey 열과 value_left 열의 값은 NaN으로 표시됩니다.


inner join 형식의 데이터 결합

mergeTempData = tempData1.merge(right = tempData2, how = 'inner', left_on = 'lkey', right_on = 'rkey', suffixes = ['_left','_right'])
mergeTempData
--------------------------------------------------
	lkey	value_left	rkey	value_right
0	foo	    1	        foo	    1
1	foo	    1	        foo	    5
2	foo	    5	        foo	    1
3	foo	    5	        foo	    5
4	bar	    2	        bar	    2    
5	baz	    3	        baz	    3

tempData1와 tempData2를 inner join (how = ‘inner’)방식으로 결합합니다.
tempData1와 tempData2에 모두 존재하는 결합 key의 값 기준으로 결합되었습니다(lkey의 ‘zoo’ 값과 rkey의 ‘exc’ 값은 모두 결합에서 제외되었습니다).


cross join 형식의 데이터 결합

mergeTempData = tempData1.merge(right = tempData2, how = 'cross', left_on = 'lkey', right_on = 'rkey', suffixes = ['_left','_right'])
mergeTempData
----------------------------------------------------------------
	lkey	value_left	rkey	value_right
0	foo	    1	        foo	    1
1	foo	    1	        bar	    2
2	foo	    1	        baz	    3
3	foo	    1	        foo	    5
4	foo	    1	        exc	    9
5	bar	    2	        foo	    1
6	bar	    2	        bar	    2
7	bar	    2	        baz	    3
8	bar	    2	        foo	    5
9	bar	    2	        exc	    9
10	baz	    3	        foo	    1
11	baz	    3	        bar	    2
12	baz	    3	        baz	    3
13	baz	    3	        foo	    5
14	baz	    3	        exc	    9
15	foo	    5	        foo	    1
16	foo	    5	        bar	    2
17	foo	    5	        baz	    3
18	foo	    5	        foo	    5
19	foo	    5	        exc	    9
20	zoo	    7	        foo	    1
21	zoo	    7	        bar	    2
22	zoo	    7	        baz	    3
23	zoo	    7	        foo	    5
24	zoo	    7	        exc	    9

tempData1와 tempData2를 데카르트 곱(how = ‘cross’)의 형식으로 결합합니다.
결합 key와 무관하게 모든 케이스의 데이터 결합을 표시해 줍니다.

이상으로 데이터 결합 시 사용할 수 있는 merge 함수에 대해서 알아 보았습니다. merge 함수 역시 데이터 전처리 시 중요하고, 자주 사용되는 함수입니다. 꼭 알아 두셔야 하는 함수이니 만큼, 많은 연습을 통해서 숙달하시기 바랍니다.


감사합니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다