일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- google apps script
- 파이썬
- PANDAS
- Apache
- Excel
- Redshift
- Kotlin
- Google Spreadsheet
- Github
- PostgreSQL
- GIT
- string
- Mac
- Tkinter
- Java
- array
- dataframe
- Google Excel
- Python
- numpy
- SQL
- PySpark
- c#
- matplotlib
- hive
- math
- django
- list
- gas
- Today
- Total
달나라 노트
Python Pandas : DataFrame.join 본문
DataFrame.join
DataFrame의 join은 merger와 비슷한 기능을 제공합니다.
먼저 test용 DataFrame을 생성합니다.
import pandas as pd
dict_a = {
'id1': [1, 2, 3, 4, 5],
'name': ['a', 'b', 'c', 'd', 'e'],
'price': [10, 20, 30, 40, 50]
}
dict_b = {
'id2': [1, 2, 3, 4],
'name': ['a', 'b', 'z', 'z'],
'price': [10, 20, 100, 100]
}
df_a = pd.DataFrame(dict_a)
df_b = pd.DataFrame(dict_b)
print(df_a)
print(type(df_a))
print(df_b)
print(type(df_b))
- Output 1
id1 name price
0 1 a 10
1 2 b 20
2 3 c 30
3 4 d 40
4 5 e 50
<class 'pandas.core.frame.DataFrame'>
id2 name price
0 1 a 10
1 2 b 20
2 3 z 100
3 4 z 100
<class 'pandas.core.frame.DataFrame'>
join은 아래처럼 사용할 수 있습니다.
df_left.join(df_right -> df_left인 DataFrame에 df_right을 join합니다. (기본적으로 left join의 형태로 진행됩니다.)
lsuffix='_l' -> 중복된 컬럼이 있을 경우 df_left에 존재하는 중복컬럼에 붙일 suffix를 지정합니다.
rsuffix='_r' -> 중복된 컬럼이 있을 경우 df_right에 존재하는 중복컬럼에 붙일 suffix를 지정합니다.
import pandas as pd
df_new = df_left.join(df_right, lsuffix='_l', rsuffix='_r')
아래 코드는 join의 예시입니다.
df_test = df_a.join(df_b, lsuffix='_l', rsuffix='_r')
print(df_test)
print(type(df_test))
- Output
id1 name_l price_l id2 name_r price_r
0 1 a 10 1.0 a 10.0
1 2 b 20 2.0 b 20.0
2 3 c 30 3.0 z 100.0
3 4 d 40 4.0 z 100.0
4 5 e 50 NaN NaN NaN
<class 'pandas.core.frame.DataFrame'>
원본 df_a, df_b입니다. 이걸 참고해서 join이 어떻게 진행되는지 직접 보면 좋습니다.
- df_a
id1 name price
0 1 a 10
1 2 b 20
2 3 c 30
3 4 d 40
4 5 e 50
- df_b
id2 name price
0 1 a 10
1 2 b 20
2 3 z 100
3 4 z 100
근데 한 가지 이상한 점은 merge method를 사용할 때에는 두 DataFrame을 병합할 때 사용할 column을 명시했는데 join에서는 그렇지 않았다는 것입니다.
그 이유는 join은 기본적으로 오른쪽 DataFrame의 index를 인식하여 왼쪽 DataFrame에 존재하는 동일한 index를 가진 행끼리 병합을 하게됩니다.
(여기서 주의할 점은 join을 할 때 DataFrame에 중복되는 index가 존재하면 Error를 발생시킵니다.)
join의 또다른 특징은 df_left와 df_right에 있는 모든 개개의 컬럼이 결과물로 반환된다는 것입니다.
또한 중복된 컬럼에 대해서는 컬럼 명에 지정한 접미어(suffix)가 붙었음을 알 수 있죠.
위 예시의 결과를 merge로 비슷하게 반환하려면 아래와 같습니다.
(df_a, df_b의 id1, id2 컬럼의 이름을 모두 id로 통일했다고 가정합시다.)
위에서 설명했던 것 처럼 merge에서는 DataFrame 병합 시에 병합의 기준이 될 key를 'left_on=['id'], right_on=['id']'의 형태로 명시했습니다.
또 한 가지의 차이는 merge에선 기준이 된 key column은 중복되어 나오지 않고 1개만 출력됩니다.
그래서 아래 결과를 보면 id라는 컬럼이 id_l, id_r 등으로 2개 출력되지 않고 id라는 딱 하나의 컬럼만 결과물에 있음을 알 수 있죠.
또한 merge에서도 중복된 컬럼을 위해 suffix를 지정 가능한데 list의 형태로 전달해야 합니다.
그리서 해당 리스트의 첫 번째 요소인 '_l'은 왼쪽 DataFrame(df_a)의 중복컬럼에 접미어로 붙었음을 알 수 있고, 두 번째 요소인 '_r'은 오른쪽 DataFrame(df_b)의 중복 컬럼에 접미어로 붙었음을 알 수 있습니다.
df_test = pd.DataFrame.merge(df_a, df_b, how='left', left_on=['id'], right_on=['id'], suffixes=['_l', '_r'])
print(df_test)
print(type(df_test))
- Output
id name_l price_l name_r price_r
0 1 a 10 a 10.0
1 2 b 20 b 20.0
2 3 c 30 z 100.0
3 4 d 40 z 100.0
4 5 e 50 NaN NaN
<class 'pandas.core.frame.DataFrame'>
첫 설명에서 join은 두 DataFrame의 index를 병합 시에 사용되는 기준 key로 사용한다고 했는데 만약 index가 아니라 특정 컬럼의 데이터를 기준 key로 사용하고싶으면 어떻게 해야할까요?
아래 예시처럼 on 인자를 사용하면 됩니다.
on=['id1']의 의미는 왼쪽 DataFrame의 id1컬럼 데이터와 오른쪽 DataFrame의 index값이 동일한 행끼리 join하겠다는 의미입니다.
따라서 id1 컬럼에있는 1이 df_b의 index = 1인 행과 연결된 것을 알 수 있죠.
df_test = df_a.join(df_b, on=['id1'], lsuffix='_l', rsuffix='_r')
print(df_test)
print(type(df_test))
- Output
id1 name_l price_l id2 name_r price_r
0 1 a 10 2.0 b 20.0
1 2 b 20 3.0 z 100.0
2 3 c 30 4.0 z 100.0
3 4 d 40 NaN NaN NaN
4 5 e 50 NaN NaN NaN
<class 'pandas.core.frame.DataFrame'>
원본 df_a, df_b입니다. 이걸 참고해서 join이 어떻게 진행되는지 직접 보면 좋습니다.
- df_a
id1 name price
0 1 a 10
1 2 b 20
2 3 c 30
3 4 d 40
4 5 e 50
- df_b
id2 name price
0 1 a 10
1 2 b 20
2 3 z 100
3 4 z 100
또한 merge에서와 마찬가지로 join의 대상이 될 DataFrame은 original DataFrame뿐만 아니라 아래 예시에 적힌 3가지 예시에서처럼 loc나 set_index등을 이용하여 DataFrame의 일부를 추출하여 사용할 수도 있습니다.
tip.set_index는 어떤 컬럼에 존재하는 값들은 index값으로 설정하는 기능을 가집니다.
즉, 아래 예시의 첫 번째 df_test에서 df_b 대신에 'df_b.set_index('id2')'를 넣어줌으로써 df_b의 id2 컬럼의 데이터를 index로 보낸 것입니다.
그리고 join은 이 index로 변경된 id2컬럼을 join시에 기준으로 사용할 것이고,
그 결과 DataFrame에서 df_b의 index는 표시되지 않음으로 결국 id2 컬럼은 반환되지 않았음을 알 수 있습니다.
df_test = df_a.join(df_b.set_index('id2'), on=['id1'], lsuffix='_l', rsuffix='_r')
print(df_test)
df_test = df_a.loc[:, ['id1']].join(df_b, on=['id1'], lsuffix='_l', rsuffix='_r')
print(df_test)
df_test = df_a.loc[:, ['id1']].join(df_b.set_index('id2'), on=['id1'], lsuffix='_l', rsuffix='_r')
print(df_test)
- Output
id1 name_l price_l name_r price_r
0 1 a 10 a 10.0
1 2 b 20 b 20.0
2 3 c 30 z 100.0
3 4 d 40 z 100.0
4 5 e 50 NaN NaN
id1 id2 name price
0 1 2.0 b 20.0
1 2 3.0 z 100.0
2 3 4.0 z 100.0
3 4 NaN NaN NaN
4 5 NaN NaN NaN
id1 name price
0 1 a 10.0
1 2 b 20.0
2 3 z 100.0
3 4 z 100.0
4 5 NaN NaN
- tip : df_b.set_index('id2')의 결과
name price
id2
1 a 10
2 b 20
3 z 100
4 z 100