이번 포스팅에서는 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의 열 교차입니다.
- 결합할 열 또는 인덱스 수준의 이름을 나타냅니다. 해당 key는 두 데이터프레임에 모두 존재해야 합니다.
- 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” 값을 갖는 범주형 유형이 있습니다.
- True인 경우 각 행의 소스에 대한 정보와 함께 “_merge”라는 열을 출력 DataFrame에 추가합니다. 문자열 인수를 제공하여 열에 다른 이름을 지정할 수 있습니다.
- 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 함수 역시 데이터 전처리 시 중요하고, 자주 사용되는 함수입니다. 꼭 알아 두셔야 하는 함수이니 만큼, 많은 연습을 통해서 숙달하시기 바랍니다.
감사합니다.