일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Mac
- GIT
- SQL
- Tkinter
- PostgreSQL
- PANDAS
- google apps script
- c#
- math
- dataframe
- Redshift
- string
- Excel
- Github
- Google Spreadsheet
- matplotlib
- gas
- list
- Java
- Kotlin
- numpy
- Python
- django
- hive
- 파이썬
- Apache
- Google Excel
- array
- PySpark
- Today
- Total
달나라 노트
Python Pandas : merge (2개의 DataFrame join하기. DataFrame join, DataFrame left join, DataFrame right join, DataFrame outer join) 본문
Python Pandas : merge (2개의 DataFrame join하기. DataFrame join, DataFrame left join, DataFrame right join, DataFrame outer join)
CosmosProject 2020. 11. 3. 14:10
DataFrame.merge
sql에서의 window function과 비슷한 기능을 pandas에서 어떻게 사용할 수 있는지를 알아봅시다.
먼저 test용 DataFrame을 생성합니다.
import pandas as pd
dict_name = {
'item_id': [1, 2, 4],
'item_name': ['a', 'b', 'd']
}
dict_price = {
'item_id': [1, 2, 3],
'price': [1000, 2000, 3000]
}
df_name = pd.DataFrame(dict_name)
df_price = pd.DataFrame(dict_price)
print(df_name)
print(type(df_name))
print(df_price)
print(type(df_price))
- Output 1
item_id item_name
0 1 a
1 2 b
2 4 d
<class 'pandas.core.frame.DataFrame'>
item_id price
0 1 1000
1 2 2000
2 3 3000
<class 'pandas.core.frame.DataFrame'>
item_id별 이름과, item_id별 가격을 담고있는 2개의 DataFrame을 생성했습니다.
DataFrame의 merge는 아래처럼 사용할 수 있습니다.
sql의 join과 동일하다고 생각하시면 됩니다.
left_df -> 왼쪽에 위치할 DataFrame
right_df -> 오른쪽에 위치할 DataFrame
how -> inner, left, right, outer 4개의 옵션 중 1개 선택하여 사용가능
left_on -> 왼쪽에 위치할 DataFrame에서 merge시에 기준이 될 컬럼이름(List의 형태로 1개 이상의 컬럼 이름 전달 가능)
right_on -> 오른쪽에 위치할 DataFrame에서 merge시에 기준이 될 컬럼이름(List의 형태로 1개 이상의 컬럼 이름 전달 가능)
pd.merge(left_df, right_df, how='inner/left/right/outer', left_on=[left_df_column], right_on=[right_df_column])
how에 들어갈 수 있는 4개의 옵션 각각에 대해 예시 DataFrame을 merge하며 살펴봅시다.
1. inner 옵션은 merge 기준이 되는 item_id 컬럼에 대해 2개의 DataFrame이 모두 가진 값만을 합쳐서 반환합니다.
2. left 옵션은 merge 기준이 되는 item_id 컬럼에 대해 left DataFrame이 모두 가진 값을 보존한 후 거기에 right DataFrame을 합쳐서 반환합니다.
item_id = 4인 상품은 df_price에 price정보가 없었으므로 NaN값으로 출력됨을 알 수 있습니다.
3. right 옵션은 merge 기준이 되는 item_id 컬럼에 대해 right DataFrame이 모두 가진 값을 보존한 후 거기에 left DataFrame을 합쳐서 반환합니다.
item_id = 3인 상품은 df_name에 item_name정보가 없었으므로 NaN값으로 출력됨을 알 수 있습니다.
4. outer 옵션은 merge 기준이 되는 item_id 컬럼에 대해 left DataFrame과 right DataFrame이 가진 모든 행을 보존한 후 거기에 동일한 item_id끼리 연결하여 반환합니다.
item_id = 4인 상품은 df_price에 price정보가 없었으므로 NaN값으로 출력됨을 알 수 있습니다.
item_id = 3인 상품은 df_name에 item_name정보가 없었으므로 NaN값으로 출력됨을 알 수 있습니다.
df_new = pd.merge(df_name, df_price, how='inner', left_on=['item_id'], right_on=['item_id'])
print(df_new)
- Output
item_id item_name price
0 1 a 1000
1 2 b 2000
df_new = pd.merge(df_name, df_price, how='left', left_on=['item_id'], right_on=['item_id'])
print(df_new)
- Output
item_id item_name price
0 1 a 1000.0
1 2 b 2000.0
2 4 d NaN
df_new = pd.merge(df_name, df_price, how='right', left_on=['item_id'], right_on=['item_id'])
print(df_price)
- Output
item_id item_name price
0 1 a 1000
1 2 b 2000
2 3 NaN 3000
df_new = pd.merge(df_name, df_price, how='outer', left_on=['item_id'], right_on=['item_id'])
print(df_new)
- Output
item_id item_name price
0 1 a 1000.0
1 2 b 2000.0
2 4 d NaN
3 3 NaN 3000.0
이제 한번 left_on, right_on의 조건에 2개의 컬럼을 조건으로 넣어봅시다.
이를 위해 테스트용 DataFrame을 생성합니다.
dict_daily_price = {
'basis_dy': [
20200101, 20200102, 20200103,
20200101, 20200102, 20200103,
20200101, 20200102, 20200103,
20200101, 20200102, 20200103, 20200104],
'item_id': [
1, 1, 1,
2, 2, 2,
3, 3, 3,
4, 4, 4, 4],
'item_name': [
'a', 'a', 'a',
'b', 'b', 'b',
'c', 'c', 'c',
'd', 'd', 'd', 'd'],
'price': [
1000, 1000, 1010,
2000, 2100, 2050,
3000, 3100, 2950,
4000, 3950, 3900, 3980],
}
dict_daily_sales = {
'basis_dy': [
20200101, 20200102, 20200103,
20200101, 20200102, 20200103,
20200101, 20200102, 20200103,
20200101, 20200102, 20200103, 20200104],
'item_id': [
1, 1, 1,
2, 2, 2,
3, 3, 3,
4, 4, 4, 4],
'item_name': [
'a', 'a', 'a',
'b', 'b', 'b',
'c', 'c', 'c',
'd', 'd', 'd', 'd'],
'quantity': [
100, 105, 98,
50, 51, 55,
201, 200, 220,
30, 40, 38, 50
]
}
df_daily_price = pd.DataFrame(dict_daily_price)
df_daily_sales = pd.DataFrame(dict_daily_sales)
print(df_daily_price)
print(type(df_daily_price))
print(df_daily_sales)
print(type(df_daily_sales))
- Output
basis_dy item_id item_name price
0 20200101 1 a 1000
1 20200102 1 a 1000
2 20200103 1 a 1010
3 20200101 2 b 2000
4 20200102 2 b 2100
5 20200103 2 b 2050
6 20200101 3 c 3000
7 20200102 3 c 3100
8 20200103 3 c 2950
9 20200101 4 d 4000
10 20200102 4 d 3950
11 20200103 4 d 3900
12 20200104 4 d 3980
basis_dy item_id item_name quantity
0 20200101 1 a 100
1 20200102 1 a 105
2 20200103 1 a 98
3 20200101 2 b 50
4 20200102 2 b 51
5 20200103 2 b 55
6 20200101 3 c 201
7 20200102 3 c 200
8 20200103 3 c 220
9 20200101 4 d 30
10 20200102 4 d 40
11 20200103 4 d 38
12 20200104 4 d 50
위에서 생성한 2개의 DataFrame 중하나는 item들의 일자별 price 정보를 담고있으며 -> df_daily_price
다른 하나는 item들의 일자별 판매 개수를 담고있습니다. -> df_daily_sales
이 2개의 DataFrame을 합쳐서 일자별 가격과 판매개수 정보를 모두 담고있는 새로운 DataFrame을 생성해봅시다.
df_new = pd.merge(df_daily_price, df_daily_sales, how='inner', left_on=['item_id', 'basis_dy'], right_on=['item_id', 'basis_dy'])
print(df_new)
- Output
basis_dy item_id item_name_x price item_name_y quantity
0 20200101 1 a 1000 a 100
1 20200102 1 a 1000 a 105
2 20200103 1 a 1010 a 98
3 20200101 2 b 2000 b 50
4 20200102 2 b 2100 b 51
5 20200103 2 b 2050 b 55
6 20200101 3 c 3000 c 201
7 20200102 3 c 3100 c 200
8 20200103 3 c 2950 c 220
9 20200101 4 d 4000 d 30
10 20200102 4 d 3950 d 40
11 20200103 4 d 3900 d 38
12 20200104 4 d 3980 d 50
위처럼 left_on과 right_on의 조건에 2개의 컬럼을 명시하면 merge가 진행될 때 item_id와 basis_dy가 모두 동일한 값을 가진 행(row)끼리 합쳐짐을 알 수 있습니다.
그리고 결과에서 보면 item_name컬럼이 item_name_x와 item_name_y 2개가 존재함을 알 수 있죠.
item_name_x는 df_daily_price에 있던 item_name컬럼의 이름에 _x라는 접미어가 붙은 것이며
item_name_y는 df_daily_sales에 있던 item_name컬럼의 이름에 _y라는 접미어가 붙은 것입니다.
이렇게 item_name 컬럼에만 접미어가 붙은 이유는 merge 대상인 두 DataFrame이 동일한 이름의 컬럼을 가지고 있었기 때문입니다.
또한 여기서 왼쪽 DataFrame에 있는 컬럼에는 _x라는 접미어가 붙고, 오른쪽 DataFrame에 있는 컬럼에는 _y라는 접미어가 붙는다는 것도 알 수 있죠.
근데 뭔가 이상합니다.
두 DataFrame에는 item_id와 basis_dy라는 중복된 컬럼도 존재하는데 왜 이 두 컬럼에는 _x, _y등의 접미어각 붙지 않았을까요?
그것을 바로 item_id, basis_dy 이 두 컬럼은 merge의 조건(left_on, right_on)으로 쓰였기 때문입니다.
또한 merge 내에서 loc를 이용하여 일부의 DataFrame에 대해 merge가 가능합니다.
아래와 같은 형식은 left_df의 key가 되는 컬럼(이 예시에서는 item_id와 basis_dy가 되겠네요.)을 기준으로 right_df의 데이터를 붙여넣으면서 중복된 컬럼도 생기지 않게 하기 위한 방법으로 사용하기 좋겠네요.
df_new = pd.merge(df_daily_price.loc[:, ['item_id', 'basis_dy']], df_daily_sales, how='inner', left_on=['item_id', 'basis_dy'], right_on=['item_id', 'basis_dy'])
print(df_new)
- Output
item_id basis_dy item_name quantity
0 1 20200101 a 100
1 1 20200102 a 105
2 1 20200103 a 98
3 2 20200101 b 50
4 2 20200102 b 51
5 2 20200103 b 55
6 3 20200101 c 201
7 3 20200102 c 200
8 3 20200103 c 220
9 4 20200101 d 30
10 4 20200102 d 40
11 4 20200103 d 38
12 4 20200104 d 50
'Python > Python Pandas' 카테고리의 다른 글
Python Pandas : DataFrame.loc & DataFrame.iloc (0) | 2020.11.04 |
---|---|
Python Pandas : DataFrame filtering (1) | 2020.11.04 |
Python Pandas : DataFrame.groupby (0) | 2020.11.02 |
Python Pandas : DataFrame.assign (0) | 2020.11.02 |
Python Pandas : DataFrame.apply & DataFrame.applymap (0) | 2020.11.02 |