Merge_join 함수로 데이터 프레임 병합하기
학습목표
- merge & join 함수 활용하기
import numpy as np
import pandas as pd
dataframe merge
- SQL의 join처럼 특정한 column을 기준으로 병합
- join 방식: how 파라미터를 통해 명시
- inner: 기본값, 일치하는 값이 있는 경우
- left: left outer join
- right: right outer join
- outer: full outer join
- join 방식: how 파라미터를 통해 명시
- pandas.merge 함수가 사용됨
customer = pd.DataFrame({'customer_id' : np.arange(6),
'name' : ['철수'"", '영희', '길동', '영수', '수민', '동건'],
'나이' : [40, 20, 21, 30, 31, 18]})
customer
customer_id | name | 나이 | |
---|---|---|---|
0 | 0 | 철수 | 40 |
1 | 1 | 영희 | 20 |
2 | 2 | 길동 | 21 |
3 | 3 | 영수 | 30 |
4 | 4 | 수민 | 31 |
5 | 5 | 동건 | 18 |
orders = pd.DataFrame({'customer_id' : [1, 1, 2, 2, 2, 3, 3, 1, 4, 9],
'item' : ['치약', '칫솔', '이어폰', '헤드셋', '수건', '생수', '수건', '치약', '생수', '케이스'],
'quantity' : [1, 2, 1, 1, 3, 2, 2, 3, 2, 1]})
orders.head()
customer_id | item | quantity | |
---|---|---|---|
0 | 1 | 치약 | 1 |
1 | 1 | 칫솔 | 2 |
2 | 2 | 이어폰 | 1 |
3 | 2 | 헤드셋 | 1 |
4 | 2 | 수건 | 3 |
- on
- join 대상이 되는 column 명시
pd.merge(customer, orders, on='customer_id', how='inner') #(테이블명1, 테이블명2)
customer_id | name | 나이 | item | quantity | |
---|---|---|---|---|---|
0 | 1 | 영희 | 20 | 치약 | 1 |
1 | 1 | 영희 | 20 | 칫솔 | 2 |
2 | 1 | 영희 | 20 | 치약 | 3 |
3 | 2 | 길동 | 21 | 이어폰 | 1 |
4 | 2 | 길동 | 21 | 헤드셋 | 1 |
5 | 2 | 길동 | 21 | 수건 | 3 |
6 | 3 | 영수 | 30 | 생수 | 2 |
7 | 3 | 영수 | 30 | 수건 | 2 |
8 | 4 | 수민 | 31 | 생수 | 2 |
pd.merge(customer, orders, on='customer_id', how='left')
customer_id | name | 나이 | item | quantity | |
---|---|---|---|---|---|
0 | 0 | 철수 | 40 | NaN | NaN |
1 | 1 | 영희 | 20 | 치약 | 1.0 |
2 | 1 | 영희 | 20 | 칫솔 | 2.0 |
3 | 1 | 영희 | 20 | 치약 | 3.0 |
4 | 2 | 길동 | 21 | 이어폰 | 1.0 |
5 | 2 | 길동 | 21 | 헤드셋 | 1.0 |
6 | 2 | 길동 | 21 | 수건 | 3.0 |
7 | 3 | 영수 | 30 | 생수 | 2.0 |
8 | 3 | 영수 | 30 | 수건 | 2.0 |
9 | 4 | 수민 | 31 | 생수 | 2.0 |
10 | 5 | 동건 | 18 | NaN | NaN |
pd.merge(customer, orders, on='customer_id', how='right')
customer_id | name | 나이 | item | quantity | |
---|---|---|---|---|---|
0 | 1 | 영희 | 20.0 | 치약 | 1 |
1 | 1 | 영희 | 20.0 | 칫솔 | 2 |
2 | 2 | 길동 | 21.0 | 이어폰 | 1 |
3 | 2 | 길동 | 21.0 | 헤드셋 | 1 |
4 | 2 | 길동 | 21.0 | 수건 | 3 |
5 | 3 | 영수 | 30.0 | 생수 | 2 |
6 | 3 | 영수 | 30.0 | 수건 | 2 |
7 | 1 | 영희 | 20.0 | 치약 | 3 |
8 | 4 | 수민 | 31.0 | 생수 | 2 |
9 | 9 | NaN | NaN | 케이스 | 1 |
pd.merge(customer, orders, on='customer_id', how='outer') #left + right 값 합친것
customer_id | name | 나이 | item | quantity | |
---|---|---|---|---|---|
0 | 0 | 철수 | 40.0 | NaN | NaN |
1 | 1 | 영희 | 20.0 | 치약 | 1.0 |
2 | 1 | 영희 | 20.0 | 칫솔 | 2.0 |
3 | 1 | 영희 | 20.0 | 치약 | 3.0 |
4 | 2 | 길동 | 21.0 | 이어폰 | 1.0 |
5 | 2 | 길동 | 21.0 | 헤드셋 | 1.0 |
6 | 2 | 길동 | 21.0 | 수건 | 3.0 |
7 | 3 | 영수 | 30.0 | 생수 | 2.0 |
8 | 3 | 영수 | 30.0 | 수건 | 2.0 |
9 | 4 | 수민 | 31.0 | 생수 | 2.0 |
10 | 5 | 동건 | 18.0 | NaN | NaN |
11 | 9 | NaN | NaN | 케이스 | 1.0 |
- index 기준으로 join하기
cust1 = customer.set_index('customer_id')
order1 = orders.set_index('customer_id')
cust1
name | 나이 | |
---|---|---|
customer_id | ||
0 | 철수 | 40 |
1 | 영희 | 20 |
2 | 길동 | 21 |
3 | 영수 | 30 |
4 | 수민 | 31 |
5 | 동건 | 18 |
order1
item | quantity | |
---|---|---|
customer_id | ||
1 | 치약 | 1 |
1 | 칫솔 | 2 |
2 | 이어폰 | 1 |
2 | 헤드셋 | 1 |
2 | 수건 | 3 |
3 | 생수 | 2 |
3 | 수건 | 2 |
1 | 치약 | 3 |
4 | 생수 | 2 |
9 | 케이스 | 1 |
pd.merge(cust1, order1, left_index=True, right_index=True) #on='customer_id' 대신 사용가능
name | 나이 | item | quantity | |
---|---|---|---|---|
customer_id | ||||
1 | 영희 | 20 | 치약 | 1 |
1 | 영희 | 20 | 칫솔 | 2 |
1 | 영희 | 20 | 치약 | 3 |
2 | 길동 | 21 | 이어폰 | 1 |
2 | 길동 | 21 | 헤드셋 | 1 |
2 | 길동 | 21 | 수건 | 3 |
3 | 영수 | 30 | 생수 | 2 |
3 | 영수 | 30 | 수건 | 2 |
4 | 수민 | 31 | 생수 | 2 |
연습문제
- 가장 많이 팔린 아이템은?
- 영희가 가장 많이 구매한 아이템은?
pd.merge(customer, orders, on='customer_id').groupby('item').sum().sort_values(by='quantity', ascending=False)
customer_id | 나이 | quantity | |
---|---|---|---|
item | |||
수건 | 5 | 51 | 5 |
생수 | 7 | 61 | 4 |
치약 | 2 | 40 | 4 |
칫솔 | 1 | 20 | 2 |
이어폰 | 2 | 21 | 1 |
헤드셋 | 2 | 21 | 1 |
pd.merge(customer, orders, on='customer_id').groupby(['name', 'item']).sum()
customer_id | 나이 | quantity | ||
---|---|---|---|---|
name | item | |||
길동 | 수건 | 2 | 21 | 3 |
이어폰 | 2 | 21 | 1 | |
헤드셋 | 2 | 21 | 1 | |
수민 | 생수 | 4 | 31 | 2 |
영수 | 생수 | 3 | 30 | 2 |
수건 | 3 | 30 | 2 | |
영희 | 치약 | 2 | 40 | 4 |
칫솔 | 1 | 20 | 2 |
pd.merge(customer, orders, on='customer_id').groupby(['name', 'item']).sum().loc['영희']
customer_id | 나이 | quantity | |
---|---|---|---|
item | |||
치약 | 2 | 40 | 4 |
칫솔 | 1 | 20 | 2 |
pd.merge(customer, orders, on='customer_id').groupby(['name', 'item']).sum().loc['영희', 'quantity']
item
치약 4
칫솔 2
Name: quantity, dtype: int64
join 함수
- 내부적으로 pandas.merge 함수 사용
- 기본적으로 index를 사용하여 left join
cust1.join(order1)
name | 나이 | item | quantity | |
---|---|---|---|---|
customer_id | ||||
0 | 철수 | 40 | NaN | NaN |
1 | 영희 | 20 | 치약 | 1.0 |
1 | 영희 | 20 | 칫솔 | 2.0 |
1 | 영희 | 20 | 치약 | 3.0 |
2 | 길동 | 21 | 이어폰 | 1.0 |
2 | 길동 | 21 | 헤드셋 | 1.0 |
2 | 길동 | 21 | 수건 | 3.0 |
3 | 영수 | 30 | 생수 | 2.0 |
3 | 영수 | 30 | 수건 | 2.0 |
4 | 수민 | 31 | 생수 | 2.0 |
5 | 동건 | 18 | NaN | NaN |
cust1.join(order1, how='inner')
name | 나이 | item | quantity | |
---|---|---|---|---|
customer_id | ||||
1 | 영희 | 20 | 치약 | 1 |
1 | 영희 | 20 | 칫솔 | 2 |
1 | 영희 | 20 | 치약 | 3 |
2 | 길동 | 21 | 이어폰 | 1 |
2 | 길동 | 21 | 헤드셋 | 1 |
2 | 길동 | 21 | 수건 | 3 |
3 | 영수 | 30 | 생수 | 2 |
3 | 영수 | 30 | 수건 | 2 |
4 | 수민 | 31 | 생수 | 2 |