이번 시간에는 merge 함수와 join함수를 사용해 dataframe을 병합해보자.
merge
를 이용한 병합은 지난 번에 공부한 concat()
함수처럼 단순히 dataframe을 row level, col level로 붙이는 것이 아닌, SQL에서의 join처럼 특정한 column을 기준으로 같은 값끼리 묶는 병합이다.
실습을 위해 모양은 다르지만 같은 이름의 column을 갖는 두 개의 dataframe을 임의로 만들어 보았다.
import numpy as np
import pandas as pd
# <in>
customer = pd.DataFrame({'customer_id' : np.arange(6),
'name' : ['철수'"", '영희', '길동', '영수', '수민', '동건'],
'나이' : [40, 20, 21, 30, 31, 18]})
customer
하나는 고객 정보가 담겨져 있는 dataframe이고
# <in>
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
하나는 고객의 주문정보가 담겨져 있는 dataframe이다.
두 dataframe은 각기 다른 정보를 가지고 있지만 customer_id라는 공통된 column을 가지고 있다.
우리가 앞으로 데이터 전처리를 할 때, 대부분의 데이터 소스들은 이와 같이 분리되어 있을 것이다.
즉, 두 테이블. 두 데이터프레임을 합쳐야 하는데, 이 때 concat()
함수를 사용한 병합은 그 의미를 갖기 힘들다.
우선 이 데이터는 공통된 column이 customer_id로 있기 때문에 cumstomer_id를 기준으로 dataframe을 병합시키는 것이 좋겠다.
이렇게 join 대상이 되는 column을 명시할 수 있는 함수가 merge
함수이다.
내부적으로 어차피 join
함수가 merge
함수를 사용하기 때문에 join과 merge 간 큰 차이는 없고 때문에
우리는 merge
함수에 대해서 공부해보고, join
함수는 그냥 사용법정도만 알아보도록 하자.
1. merge() 함수
# <in>
pd.merge(customer, orders)
merge
함수는 on parameter를 갖는데, join의 대상이 되는 column을 명시하면 된다.
default값으로 None을 갖으며, 이 경우 이름이 같은 것을 자동으로 지정하는 것으로 보인다.
또한 merge
함수는 how parameter도 갖는데, inner, left, right, outer를 인자로 받는다.
inner는 두 dataframe에서 join대상에서 value값이 일치하는 것만을 반환한다.
left는 왼쪽 dataframe(merge 함수에서 첫 번째로 입력한 dataframe), right는 오른쪽 dataframe( merge 함수에서 두 번째로 입력한 dataframe)을 기준으로 index를 반환한다.
때문에 inner에서는 NaN값이 존재할 수 없고, left, right에선 NaN값이 존재할 수 있다.
outer에서는 첫 번째, 두 번째 dataframe의 인덱스를 모두 다루기 때문에 확률적으로 NaN값이 가장 많이 나올 것이다.
이번엔 특정 column이 아닌 column자체를 index로 지정하여 index기준으로 join하는 방법에 대해서 공부해보겠다. 순서는 다르지만, 개념이나 결과는 같다.
우선 우리가 임의로 만들었던 두 dataframe의 id column을 각각 해당 dataframe의 index로 만들어보자.
# <in>
cust1 = customer.set_index('customer_id')
orders1 = orders.set_index('customer_id')
cust1
orders1
이제 두 dataframe은 customer_id column을 index로 갖고 있다.
merge() 함수의 left_index, right_index parameter
- left_index : on parameter와는 다르게 column name이 다를 경우 join으로 연결할 때, 왼쪽 dataframe의 index를 사용할 지 정할 수 있다. default값은 False이다.
- right_index : on parameter와는 다르게 column name이 다를 경우 join으로 연결할 때, 오른쪽 dataframe의 index를 사용할 지 정할 수 있다. default값은 False이다.
# <in>
pd.merge(cust1, order1, left_index=True, right_index=True)
merge()
함수에서 on parameter에 customer_id를 지정한 것과 같은 결과 값을 갖는다.
물론 0-based 인덱스가 없지만
연습문제
연습문제를 통해 merge
함수와 groupby
함수를 복습해보자.
Q. 가장 많이 팔린 아이템은?
1. 우선 처음부터의 과정을 생각하면 두 dataframe을 병합해줘야 할 것이다. 두 dataframe이 live하게 row level, col level 그대로 병합할 수 있는 shape이 아니기 때문에 merge
함수를 통해 병합한다.
# <in>
pd.merge(customer, orders, on = 'customer_id')
잘 병합이 잘 되었다. 주문을 하지 않은 고객이나, 고객 정보에 없는 주문 정보는 필요가 없기 때문에(잘못된 주문) how parameter를 inner값으로 지정하는 것이 올바를 것이다.
이제 만들어진 하나의 dataframe을 item 기준 groupby
함수를 사용하여 합계를 얻어보자.
# <in>
pd.merge(customer, orders, on = 'customer_id').groupby('item').sum()
item별 합계가 groupby
함수를 통해 잘 정리되었다.
우리에게 필요한 data는 가장 많이 팔린 상품이었다.
이제 dataframe에서 quantity value을 내림차순을 나열해보자.
# <in>
pd.merge(customer, orders, on = 'customer_id').groupby('item').sum().sort_values(by = 'quantity', ascending = False)
.sort_values(by = 'quantity')
로 quantity column의 value를 기준으로 정열 명령하고,
.sort_value(by = 'quantity, ascending = False )
로 내림차순을 명령했다.
이제 dataframe에서 quantity 만 추출해보자.
# <in>
pd.merge(customer, orders, on = 'customer_id').groupby('item').sum().sort_values(by = 'quantity', ascending = False)['quantity']
가장 많이 팔린 상품은 수건임을 확인할 수 있다.
Q. 영희가 가장 많이 구매한 아이템은?
다시 처음부터 두 dataframe을 병합하는 것부터 시작하자.
# <in>
pd.merge(customer, orders, on = 'customer_id')
이 dataframe에서 우리는 영희가 주문한 상품에만 관심이 있다. 그렇다면 나는 name column을 dataframe의 index로 지정해보겠다.
그리고 loc
함수를 사용하여 '영희'를 index로 갖는 row의 item, quantity column 만을 추출하겠다.
# <in>
pd.merge(customer, orders, on = 'customer_id').set_index('name').loc['영희',['item','quantity']]
여기서 전의 방법을 사용해 dataframe을 quantity 기준 내림차순 정열해주겠다.
# <in>
pd.merge(customer, orders, on = 'customer_id').set_index('name').loc['영희',['item','quantity']].sort_values(by = 'quantity', ascending = False)
영희가 가장 많이 구매한 아이템은 치약으로 3개를 구매했다.
이제 join
함수를 사용하는 방법을 간단하게 공부해보자. join
함수는 내부적으로 pandas.merge
함수를 사용하여 기본적으론 index를 사용하여 left join한다.
# <in>
cust1.join(order1)
이전에 customer_id를 index로 지정한 cust1과 order1 dataframe을 사용했다.
기본적으로 join
함수는 left join을 채택하기 때문에, cust1에서는 존재하지만 order1에선 존재하지 않는 customer_id 5번의 동건이 반환된 dataframe에 존재하게 되었고 때문에 NaN값을 반환했다.
NaN값을 취급하기 싫다면 merge
함수와 마찬가지로 how parameter를 사용할 수 있다.
# <in>
cust1.join(order1, how = 'inner')
'python > pandas' 카테고리의 다른 글
21. pandas DataFrame - concat 함수. dataframe 병합 (0) | 2023.02.26 |
---|---|
20. pandas DataFrame - stack, unstack 함수 (0) | 2023.02.26 |
19. pandas DataFrame - pivot, pivot_table 함수 (0) | 2023.02.26 |
18. pandas DataFrame - transfrom함수 (2) | 2023.02.26 |
17. pandas DataFrame - groupby (0) | 2023.02.22 |