본문 바로가기
데이터분석/Pandas

[Python] Pandas : Dataframe 함수 - merge()

by 코듀킹 2024. 8. 16.

데이터 분석을 하다 보면, 여러 개의 데이터프레임을 결합해야 하는 경우가 자주 발생합니다. Pandas의 merge() 함수는 이런 작업을 수행할 때 매우 유용한 도구입니다. 이 글에서는 merge() 함수의 사용법과 다양한 옵션들을 예시와 함께 자세히 설명하겠습니다.

 

1. 기본 사용법, on 매개변수

merge() 함수는 SQL의 JOIN 연산과 유사한 방식으로 두 개의 데이터프레임을 합칠 수 있습니다. 기본적인 사용법은 다음과 같습니다:

import pandas as pd

# 예제 데이터프레임 생성
df1 = pd.DataFrame({
    'key': ['A', 'B', 'C', 'D'],
    'value1': [1, 2, 3, 4]
})

df2 = pd.DataFrame({
    'key': ['B', 'D', 'E', 'F'],
    'value2': [5, 6, 7, 8]
})

# 두 데이터프레임을 key 열을 기준으로 결합
merged_df = pd.merge(df1, df2, on='key')
merged_df

 

위의 예제에서 df1과 df2는 key 열을 기준으로 결합됩니다. 결과는 다음과 같습니다:

 

기본적으로, merge()는 교집합 방식(inner join)을 사용하여 두 데이터프레임을 결합합니다. 즉, 양쪽 데이터프레임 모두에 존재하는 key 값만 결과에 포함됩니다.

 

만약 여기서 기준으로 결합하려고 하는 열의 이름이 서로 다르다면, left_on, right_on 옵션을 사용할 수 있습니다.

# 예제 데이터프레임 생성
df3 = pd.DataFrame({
    'key1': ['A', 'B', 'C', 'D'],
    'value1': [1, 2, 3, 4]
})

df4 = pd.DataFrame({
    'key2': ['B', 'D', 'E', 'F'],
    'value2': [5, 6, 7, 8]
})

pd.merge(df3, df4, left_on='key1', right_on='key2')

 

응용

두 데이터 프레임에 겹치는 여러 열을 기준으로 merge를 하고 싶을 때는 아래와 같이 intersection 함수를 사용할 수 있다.

pd.merge(df3, df4, left_on=df3.columns.intersection(df4.columns).tolist())

 

2. how 옵션: 다양한 결합 방식

merge() 함수는 how 매개변수를 통해 다양한 결합 방식을 제공합니다. 다음은 주요 결합 방식들입니다:

  • inner: 기본값으로, 양쪽 데이터프레임에 모두 존재하는 키 값만 포함합니다. how를 사용하지 않는 경우, 디폴트 값은 inner로 설정되어 있습니다.
  • left: 왼쪽 데이터프레임의 모든 키 값을 포함하고, 오른쪽 데이터프레임에서 일치하는 값이 없는 경우 NaN으로 채웁니다.
  • right: 오른쪽 데이터프레임의 모든 키 값을 포함하고, 왼쪽 데이터프레임에서 일치하는 값이 없는 경우 NaN으로 채웁니다.
  • outer: 양쪽 데이터프레임의 모든 키 값을 포함하며, 일치하지 않는 값들은 NaN으로 채웁니다.

예제를 통해 살펴보겠습니다:

# Left Join 예시
left_merged = pd.merge(df1, df2, on='key', how='left')
print("Left Join 결과:\n", left_merged)

# Right Join 예시
right_merged = pd.merge(df1, df2, on='key', how='right')
print("Right Join 결과:\n", right_merged)

# Outer Join 예시
outer_merged = pd.merge(df1, df2, on='key', how='outer')
print("Outer Join 결과:\n", outer_merged)

 

각 결과는 다음과 같습니다:

 

3. 결합 후 처리: suffixes 옵션

동일한 이름을 가진 열이 두 데이터프레임에 존재할 경우, merge()는 자동으로 열 이름에 접미사를 추가합니다. 기본 접미사는 _x, _y이지만, suffixes 옵션을 통해 이를 변경할 수 있습니다:

# suffixes 옵션 사용 예시
df5 = pd.DataFrame({
    'key': ['A', 'B', 'C'],
    'value': [100, 200, 300]
})

df6 = pd.DataFrame({
    'key': ['B', 'C', 'D'],
    'value': [400, 500, 600]
})

suffix_merged = pd.merge(df5, df6, on='key', suffixes=('_left', '_right'))
suffix_merged

 

 

4. 여러 키를 사용한 결합

여러 열을 기준으로 데이터를 결합할 수도 있습니다. 이를 위해 on 매개변수에 열 이름의 리스트를 전달하면 됩니다:

df7 = pd.DataFrame({
    'key1': ['A', 'B', 'C'],
    'key2': ['X', 'Y', 'Z'],
    'value3': [10, 20, 30]
})

df8 = pd.DataFrame({
    'key1': ['A', 'B', 'D'],
    'key2': ['X', 'Y', 'W'],
    'value4': [40, 50, 60]
})

# 두 개의 열을 기준으로 결합
multi_key_merged = pd.merge(df7, df8, on=['key1', 'key2'], how='inner')
multi_key_merged

 

5. 인덱스를 기준으로 결합

때때로, 인덱스를 기준으로 데이터를 결합해야 할 때가 있습니다. merge() 함수는 left_index와 right_index 옵션을 사용하여 이 기능을 제공합니다:

df1 = pd.DataFrame({
    'key': ['A', 'B', 'C', 'D'],
    'value1': [1, 2, 3, 4]
})

df2 = pd.DataFrame({
    'key': ['B', 'D', 'E', 'F'],
    'value2': [5, 6, 7, 8]
})

# key 열을 인덱스로 변환
df1_indexed = df1.set_index('key')
df2_indexed = df2.set_index('key')

# 인덱스를 기준으로 결합
index_merged = pd.merge(df1_indexed, df2_indexed, left_index=True, right_index=True, how='inner')
index_merged

 

추가 설명

 

  • left_index=True: 첫 번째 데이터프레임 (df1_indexed)의 인덱스를 결합 기준으로 사용하겠다는 뜻입니다.
  • right_index=True: 두 번째 데이터프레임 (df2_indexed)의 인덱스를 결합 기준으로 사용하겠다는 뜻입니다.
  • how='inner': 교집합(inner join) 방식으로 결합하겠다는 뜻입니다. 즉, 두 데이터프레임의 인덱스 값이 모두 일치하는 경우에만 결과에 포함됩니다.

 

이를 응용하면, 인덱스와 컬럼을 대상으로 merge함수를 사용할 수도 있습니다.

# df1의 인덱스를 기준으로, df2의 'key' 열과 결합
pd.merge(df1_indexed, df2, left_index=True, right_on='key')

 

6. sort 옵션

결합 후 결과 데이터프레임을 조인 키를 기준으로 정렬할지 여부를 지정합니다. 기본값은 False이며, True로 설정하면 on으로 설정한 열을 기준으로 오름차순 정렬을 하게 됩니다. 

df9 = pd.DataFrame({
    'key': ['D', 'C', 'B', 'A'],
    'value1': [1, 2, 3, 4]
})

df10 = pd.DataFrame({
    'key': ['F', 'E', 'D', 'B'],
    'value2': [5, 6, 7, 8]
})

pd.merge(df9, df10, on='key', sort=True)

 

 

만약 sort=True을 하지 않았다면, 아래와 같은 결과가 출력된다.

pd.merge(df9, df10, on='key')

 

 

내림차순 정렬은 지원하지 않으나, 만약 내림차순 정렬을 하고 싶다면, sort_values 함수를 별도로 사용하면 됩니다.

pd.merge(df1, df2, on='key').sort_values(by='key', ascending=False)

7. indicator 옵션

indicator 옵션을 사용하면, 결합된 데이터프레임에 _merge라는 열을 추가하여 각 행이 왼쪽 데이터프레임에서만 왔는지, 오른쪽 데이터프레임에서만 왔는지, 또는 양쪽 데이터프레임에서 모두 왔는지를 표시할수도 있습니다.

pd.merge(df1, df2, on='key', how='outer', indicator=True)

 

8. validate 옵션

결합 전에 데이터프레임의 조인 유형을 검증합니다. 결합이 예상된 방식으로 이루어졌는지 확인하는 데 사용됩니다. 예를 들어, validate='one_to_one'을 지정하면 각 키가 양쪽 데이터프레임에서 유일한 값이어야 합니다.

  • 옵션:
    • 'one_to_one': 두 데이터프레임의 키가 유일한 경우.
    • 'one_to_many': 왼쪽 데이터프레임의 키가 유일하고 오른쪽은 중복될 수 있는 경우.
    • 'many_to_one': 오른쪽 데이터프레임의 키가 유일하고 왼쪽은 중복될 수 있는 경우.
    • 'many_to_many': 양쪽 데이터프레임의 키가 중복될 수 있는 경우.
# 예제 데이터프레임
df1 = pd.DataFrame({
    'key': ['A', 'B', 'C'],
    'value1': [1, 2, 3]
})

df2 = pd.DataFrame({
    'key': ['A', 'A', 'B', 'C', 'C', 'C'],
    'value2': [4, 5, 6, 7, 8, 9]
})

# one_to_many 검증
pd.merge(df1, df2, on='key', validate='one_to_many')

 

만약 validate의 값으로 'one_to_one'을 사용했다면, 오류가 뜨게됩니다.

pd.merge(df1, df2, on='key', validate='one_to_one

 

9. reduce() 함수 : 멀티 join

reduce() 함수는 파이썬의 functools 모듈에서 제공되는 함수로, 여러 개의 데이터프레임을 순차적으로 병합할 때 유용하게 사용할 수 있습니다. reduce() 함수를 사용하면, 여러 개의 데이터프레임을 간단한 코드로 연속적으로 merge()할 수 있습니다.

reduce() 함수는 두 개의 인수를 사용하는 함수와 이터러블(여러 개의 데이터프레임 리스트 등)을 입력받아, 이터러블의 첫 번째 요소부터 순차적으로 적용된 결과를 반환합니다. 다음은 여러 개의 데이터프레임을 reduce()를 사용하여 한 번에 merge()하는 방법입니다.

 

import pandas as pd
from functools import reduce

# 예제 데이터프레임 생성
df1 = pd.DataFrame({
    'key': ['A', 'B', 'C'],
    'value1': [1, 2, 3]
})

df2 = pd.DataFrame({
    'key': ['A', 'B', 'D'],
    'value2': [4, 5, 6]
})

df3 = pd.DataFrame({
    'key': ['A', 'B', 'C', 'E'],
    'value3': [7, 8, 9, 10]
})

# 데이터프레임 리스트 생성
dfs = [df1, df2, df3]

# reduce를 사용하여 다중 merge 수행
result = reduce(lambda left, right: pd.merge(left, right, on='key', how='outer'), dfs)
result

 

만약 여기서 how='left'를 하면 df1['key'] 기준으로 left join 하게 되고, how='right'를 하게 되면, df3['key'] 기준으로 right join 하게 됩니다. 그리고 how='inner'를 하면, key는 A와 B만 남습니다.

 

reduce 함수를 사용한 위 코드를 풀어서 쓰면 이렇게 됩니다. 훨씬 코드가 간결해지기 때문에 reduce()를 사용하는 것입니다.

import pandas as pd

# 두 개의 데이터프레임을 병합하는 함수 정의
def merge_two_dfs(left, right):
    return pd.merge(left, right, on='key', how='outer')

# 데이터프레임 리스트 정의
dfs = [df1, df2, df3]

# 수동으로 reduce와 같은 방식으로 병합하기
result = dfs[0]  # 첫 번째 데이터프레임을 초기값으로 설정
for i in range(1, len(dfs)):  # 두 번째 데이터프레임부터 차례로 병합
    result = merge_two_dfs(result, dfs[i])

result

 

참고

댓글