데이터프레임 병합하기(merge, concat)

복수의 데이터프레임을 하나로 만드는 과정을 만져보자

1
2
df1 = pd.DataFrame({'국어':[87, 69], '수학':[77,96]}, index=['홍길동', '임꺽정'])
df1

국어 수학
홍길동 87 77
임꺽정 69 96
1
2
df2 = pd.DataFrame({'국어':[82,81], '영어':[86,90]}, index=['전봉준','장길산'])
df2

국어 영어
전봉준 82 86
장길산 81 90
1
2
df3 = pd.DataFrame({'국어':[82,81], '영어':[86,90]}, index=['전봉준','장길산'])
df3

국어 영어
전봉준 82 86
장길산 81 90

concat함수

세로로 병합하기(그냥 아래로 붙이는거)

데이터프레임끼리 컬럼이 달라도 된다. (없는 컬럼엔 NaN값으로 알아서 채워짐)
근데, 데이터프레임간에 컬럼이 서로 다르면 sort=False를 넣어줘야 경고가 발생하지 않아

[sort 파라미터는 컬럼 이름을 정렬해주는 옵션]
1
2
df_concat1 = pd.concat([df1, df2, df3], sort=False)
df_concat1

국어 수학 영어
홍길동 87 77.0 NaN
임꺽정 69 96.0 NaN
전봉준 82 NaN 86.0
장길산 81 NaN 90.0
전봉준 82 NaN 86.0
장길산 81 NaN 90.0
가로로 병합하기 (위에 언급했듯이 axis=1 옵션만 주면 되)
1
2
df_concat2 = pd.concat([df1, df2, df3], sort=False, axis=1)
df_concat2

국어 수학 국어 영어 국어 영어
홍길동 87.0 77.0 NaN NaN NaN NaN
임꺽정 69.0 96.0 NaN NaN NaN NaN
전봉준 NaN NaN 82.0 86.0 82.0 86.0
장길산 NaN NaN 81.0 90.0 81.0 90.0

쉽지?? 넘어가도록 할게

1
2


merge함수

공통 컬럼을 기준으로 병합하기 가능
1
2
3
pd.merge(df1, df2)

df1이랑 df2는 서로 겹치는 게 없어서 컬럼만 나오네

국어 수학 영어
1
2
3
4
pd.merge(df1, df2, how='outer')

서로 겹치지 않는 부분은 그냥 NaN으로 채우면서 서로 병합하는거야
방법은 how = 'outer' 파라미터를 쓰면 돼

국어 수학 영어
0 87 77.0 NaN
1 69 96.0 NaN
2 82 NaN 86.0
3 81 NaN 90.0
how 파라미터는 outer, inner만 있는게 아니야.
left, right도 있어
1
2
3
4
pd.merge(df1, df2, how='left')

왼쪽꺼를 기준으로 놓고, 오른쪽의 데이터를 가져와서 합병시키되,
오른쪽에서 가져올 데이터가 없는 자리에는 NaN값으로 채워 넣어줘

국어 수학 영어
0 87 77 NaN
1 69 96 NaN
1
2
3
pd.merge(df1, df2, how='right')

마찬가지로 이거는 오른쪽을 기준으로

국어 수학 영어
0 82 NaN 86
1 81 NaN 90
merge 함수와 비슷한 기능의 join 이라는 함수도 있어

근데 join함수는 merge랑 완전 같은 기능이라 따로 정리는 안할거야
이러한 기능이 필요할 땐 merge함수를 쓰면 되지

1
2


1
2


중복되는 데이터가 존재하는 경우의 열단위 병합(merge)

  • 어떻게든 조합을 만들어내니까 너무 걱정마
1
2
df_1 = pd.DataFrame({'아이디':['a','b','c','d'], '결제금액':[1000, 1200, 1700, 3200]})
df_1

아이디 결제금액
0 a 1000
1 b 1200
2 c 1700
3 d 3200
1
2
df_2 = pd.DataFrame({'아이디':['a','b','c','d'], '적립금':[120, 1700, 200, 320]})
df_2

아이디 적립금
0 a 120
1 b 1700
2 c 200
3 d 320
1
pd.merge(df_1, df_2)

아이디 결제금액 적립금
0 a 1000 120
1 b 1200 1700
2 c 1700 200
3 d 3200 320

일단 기본 merge를 시켜서 모든 경우의수를 다 봐
그리고 나서 수정을 하든말든 오키?

겹치는 컬럼이 2개 이상인 경우에는?

간단해. 이럴때는 ‘on’ 이라는 파라미터를 사용하면 on값을 기준으로 merge가 되

1
2
3
4
df_a = pd.DataFrame({'고객명':['길동','길산'],
'데이터':['2000','1700'],
'날짜':['2020-05-08', '2020-06-08']})
df_a

고객명 데이터 날짜
0 길동 2000 2020-05-08
1 길산 1700 2020-06-08
1
2
3
4
df_b = pd.DataFrame({'고객명':['길동','길산'],
'데이터':['21세','17세'],
})
df_b

고객명 데이터
0 길동 21세
1 길산 17세
1
pd.merge(df_a, df_b)

고객명 데이터 날짜

merge가 되지 않아. 왜냐믄 공통되는 컬럼이 2개가 되니깐 둘 다 참조를 하게되서.. 두 컬럼 사이에 교집합이 없으니 merge를 해도 소용이 없는거야

1
pd.merge(df_a, df_b, on='고객명')

고객명 데이터_x 날짜 데이터_y
0 길동 2000 2020-05-08 21세
1 길산 1700 2020-06-08 17세

자 on 파라미터로 기준을 고객명으로 줬더니 출력이 됐어.
이거를 보면 알 수 있듯이, 기준열은 아니면서 이름이 같은 열인 경우에는 _x 와 _y가 붙어

1
2


_x 랑 _y가 좀 그렇지? 그러면 컬럼명을 변경을 하자

1
2
3
xx = pd.merge(df_a, df_b, on='고객명')
xx = xx.rename(columns={'데이터_x': '금액', '데이터_y':'나이'})
xx

고객명 금액 날짜 나이
0 길동 2000 2020-05-08 21세
1 길산 1700 2020-06-08 17세

Good Job!

1
2


공통 컬럼은 존재하지 않지만, 우리가 이름이 다른 두 컬럼을 지정해서 merge하라고 명령 할수도 있어
1
df_a

고객명 데이터 날짜
0 길동 2000 2020-05-08
1 길산 1700 2020-06-08
1
2
df_b = df_b.rename(columns={'고객명':'이름'})
df_b

이름 데이터
0 길동 21세
1 길산 17세

자 해보자

1
2


1
2
merged = pd.merge(df_a, df_b, left_on='고객명', right_on='이름')
merged

고객명 데이터_x 날짜 이름 데이터_y
0 길동 2000 2020-05-08 길동 21세
1 길산 1700 2020-06-08 길산 17세
왼쪽의 고객명과 오른쪽의 이름이 같은 데이터를 병합하라는 의미네. ㅇㅋ 이렇게 되는구나. 그럼 이제 겹치는 컬럼을 지우자
1
2
merged.drop('이름',axis=1, inplace=True)
merged

고객명 데이터_x 날짜 데이터_y
0 길동 2000 2020-05-08 21세
1 길산 1700 2020-06-08 17세
1
2


??? : merge는 항상 컬럼 기준이야??

오~ 너 참 똑똑이구나?

1
2


Index를 기준으로 당연히 merge가 되

left_index, right_index 파라미터를 이용하면되는데,, 일단 해보자고

1
2


1
2
역사 = pd.DataFrame({'역사':[90,82]}, index=['필구','봉구'])
역사

역사
필구 90
봉구 82
1
2
수학 = pd.DataFrame({'수학':[81,92]}, index=['필구','맹구'])
수학

수학
필구 81
맹구 92
1
2
역사수학 = pd.merge(역사, 수학, left_index=True, right_index=True)
역사수학

역사 수학
필구 90 81

두 데이터에서 겹치는 index인 필구만 잡아서 추가해주네 ㅇㅋ?

1
2
역사수학 = pd.merge(역사, 수학, left_index=True, right_index=True, how='outer')
역사수학

역사 수학
맹구 NaN 92.0
봉구 82.0 NaN
필구 90.0 81.0
1
2


그러면 이런 경우에는 어떻게 해야하는 거야?

1
2
역사 = pd.DataFrame({'역사':[90,82]}, index=['필구','봉구'])
역사

역사
필구 90
봉구 82
1
2
수학 = pd.DataFrame({'수학':[81,92],'이름':['필구','봉구']})
수학

수학 이름
0 81 필구
1 92 봉구

이 두개를 merge하고 싶은데,
서로 참조시킬 것이 하나는 index에 있고, 다른 하나는 column으로 갖고 있잖아..

이럴때 바로 left/right_index와 left/right_on을 응용해서 쉐킷쉐킷!

1
2


1
2
역사수학_ = pd.merge(역사,수학, left_index=True, right_on='이름')
역사수학_

역사 수학 이름
0 90 81 필구
1 82 92 봉구

정리만 해주고 끝내자 힘들다!

1
2
3
역사수학_.index = 역사수학_['이름'].values
역사수학_.drop('이름', axis=1, inplace=True)
역사수학_

역사 수학
필구 90 81
봉구 82 92
You need to set install_url to use ShareThis. Please set it in _config.yml.
You forgot to set the business or currency_code for Paypal. Please set it in _config.yml.

Comments

You forgot to set the shortname for Disqus. Please set it in _config.yml.