🔥알림🔥
① 테디노트 유튜브 -
구경하러 가기!
② LangChain 한국어 튜토리얼
바로가기 👀
③ 랭체인 노트 무료 전자책(wikidocs)
바로가기 🙌
④ RAG 비법노트 LangChain 강의오픈
바로가기 🙌
⑤ 서울대 PyTorch 딥러닝 강의
바로가기 🙌
#08-Pandas(판다스) Concat(연결), Merge(병합)
이번 에피소드에서는 Pandas DataFrame의 여러 개의 DataFrame으로 이루어진 데이터를 합치는 방법인 concat()
(연결), merge()
(병합)에 대하여 다뤄 보도록 하겠습니다.
concat()
은 2개 이상의 DataFrame을 행 혹은 열 방향으로 연결합니다.
merge()
는 2개의 DataFrame을 특정 Key를 기준으로 병합할 때 활용하는 메서드입니다.
모듈 import
from IPython.display import Image
import numpy as np
import pandas as pd
import seaborn as sns
데이터셋 로드
1월 부터 6월 까지 상반기 데이터 로드
gas1 = pd.read_csv('https://bit.ly/3znNjEX', encoding='euc-kr')
print(gas1.shape)
gas1.head()
(90590, 11)
번호 | 지역 | 상호 | 주소 | 기간 | 상표 | 셀프여부 | 고급휘발유 | 휘발유 | 경유 | 실내등유 | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190101 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
1 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190102 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
2 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190103 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
3 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190104 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
4 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190105 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
gas2 = pd.read_csv('https://bit.ly/2Sv5oAn', encoding='euc-kr')
7월 부터 12월 까지 하반기 데이터 로드
print(gas2.shape)
gas2.head()
(91124, 11)
번호 | 지역 | 상호 | 주소 | 기간 | 상표 | 셀프여부 | 고급휘발유 | 휘발유 | 경유 | 실내등유 | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190701 | SK에너지 | 셀프 | 1777 | 1577 | 1477 | 0 |
1 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190702 | SK에너지 | 셀프 | 1777 | 1577 | 1477 | 0 |
2 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190703 | SK에너지 | 셀프 | 1777 | 1577 | 1477 | 0 |
3 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190704 | SK에너지 | 셀프 | 1777 | 1577 | 1477 | 0 |
4 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190705 | SK에너지 | 셀프 | 1777 | 1577 | 1477 | 0 |
concat() - 데이터 연결
concat()
은 DataFrame을 연결합니다.
단순하게 지정한 DataFrame을 이어서 연결합니다.
행 방향으로 연결
기본 값인 axis=0
이 지정되어 있고, 행 방향으로 연결합니다.
또한, 같은 column을 알아서 찾아서 데이터를 연결합니다.
pd.concat([gas1, gas2])
번호 | 지역 | 상호 | 주소 | 기간 | 상표 | 셀프여부 | 고급휘발유 | 휘발유 | 경유 | 실내등유 | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190101 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
1 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190102 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
2 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190103 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
3 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190104 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
4 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190105 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
91119 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20191227 | GS칼텍스 | 셀프 | 0 | 1540 | 1389 | 1100 |
91120 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20191228 | GS칼텍스 | 셀프 | 0 | 1540 | 1389 | 1100 |
91121 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20191229 | GS칼텍스 | 셀프 | 0 | 1540 | 1389 | 1100 |
91122 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20191230 | GS칼텍스 | 셀프 | 0 | 1540 | 1389 | 1100 |
91123 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20191231 | GS칼텍스 | 셀프 | 0 | 1540 | 1389 | 1100 |
181714 rows × 11 columns
연결시 위와 같이 index가 초기화가 되지 않아 전체 DataFrame의 개수와 index가 맞지 않는 모습입니다.
pd.concat([gas1, gas2]).iloc[90588:90593]
번호 | 지역 | 상호 | 주소 | 기간 | 상표 | 셀프여부 | 고급휘발유 | 휘발유 | 경유 | 실내등유 | |
---|---|---|---|---|---|---|---|---|---|---|---|
90588 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20190629 | GS칼텍스 | 셀프 | 0 | 1529 | 1389 | 0 |
90589 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20190630 | GS칼텍스 | 셀프 | 0 | 1529 | 1389 | 0 |
0 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190701 | SK에너지 | 셀프 | 1777 | 1577 | 1477 | 0 |
1 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190702 | SK에너지 | 셀프 | 1777 | 1577 | 1477 | 0 |
2 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190703 | SK에너지 | 셀프 | 1777 | 1577 | 1477 | 0 |
연결 하면서 index를 무시하고 연결 할 수 있습니다.
gas = pd.concat([gas1, gas2], ignore_index=True)
gas
번호 | 지역 | 상호 | 주소 | 기간 | 상표 | 셀프여부 | 고급휘발유 | 휘발유 | 경유 | 실내등유 | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190101 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
1 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190102 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
2 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190103 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
3 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190104 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
4 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190105 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
181709 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20191227 | GS칼텍스 | 셀프 | 0 | 1540 | 1389 | 1100 |
181710 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20191228 | GS칼텍스 | 셀프 | 0 | 1540 | 1389 | 1100 |
181711 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20191229 | GS칼텍스 | 셀프 | 0 | 1540 | 1389 | 1100 |
181712 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20191230 | GS칼텍스 | 셀프 | 0 | 1540 | 1389 | 1100 |
181713 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20191231 | GS칼텍스 | 셀프 | 0 | 1540 | 1389 | 1100 |
181714 rows × 11 columns
열 방향으로 연결
열(column) 방향으로 연결 가능하며, axis=1
로 지정합니다.
# 실습을 위한 DataFrame 임의 분할
gas1 = gas.iloc[:, :5]
gas2 = gas.iloc[:, 5:]
gas1.head()
번호 | 지역 | 상호 | 주소 | 기간 | |
---|---|---|---|---|---|
0 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190101 |
1 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190102 |
2 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190103 |
3 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190104 |
4 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190105 |
gas2.head()
상표 | 셀프여부 | 고급휘발유 | 휘발유 | 경유 | 실내등유 | |
---|---|---|---|---|---|---|
0 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
1 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
2 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
3 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
4 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
같은 index 행끼리 연결됩니다.
pd.concat([gas1, gas2], axis=1)
번호 | 지역 | 상호 | 주소 | 기간 | 상표 | 셀프여부 | 고급휘발유 | 휘발유 | 경유 | 실내등유 | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190101 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
1 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190102 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
2 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190103 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
3 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190104 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
4 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190105 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
181709 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20191227 | GS칼텍스 | 셀프 | 0 | 1540 | 1389 | 1100 |
181710 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20191228 | GS칼텍스 | 셀프 | 0 | 1540 | 1389 | 1100 |
181711 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20191229 | GS칼텍스 | 셀프 | 0 | 1540 | 1389 | 1100 |
181712 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20191230 | GS칼텍스 | 셀프 | 0 | 1540 | 1389 | 1100 |
181713 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20191231 | GS칼텍스 | 셀프 | 0 | 1540 | 1389 | 1100 |
181714 rows × 11 columns
merge() - 병합
서로 다른 구성의 DataFrame이지만, 공통된 key값(컬럼)을 가지고 있다면 병합할 수 있습니다.
df1 = pd.DataFrame({
'고객명': ['박세리', '이대호', '손흥민', '김연아', '마이클조던'],
'생년월일': ['1980-01-02', '1982-02-22', '1993-06-12', '1988-10-16', '1970-03-03'],
'성별': ['여자', '남자', '남자', '여자', '남자']})
df1
고객명 | 생년월일 | 성별 | |
---|---|---|---|
0 | 박세리 | 1980-01-02 | 여자 |
1 | 이대호 | 1982-02-22 | 남자 |
2 | 손흥민 | 1993-06-12 | 남자 |
3 | 김연아 | 1988-10-16 | 여자 |
4 | 마이클조던 | 1970-03-03 | 남자 |
df2 = pd.DataFrame({
'고객명': ['김연아', '박세리', '손흥민', '이대호', '타이거우즈'],
'연봉': ['2000원', '3000원', '1500원', '2500원', '3500원']})
df2
고객명 | 연봉 | |
---|---|---|
0 | 김연아 | 2000원 |
1 | 박세리 | 3000원 |
2 | 손흥민 | 1500원 |
3 | 이대호 | 2500원 |
4 | 타이거우즈 | 3500원 |
pd.merge(df1, df2)
고객명 | 생년월일 | 성별 | 연봉 | |
---|---|---|---|---|
0 | 박세리 | 1980-01-02 | 여자 | 3000원 |
1 | 이대호 | 1982-02-22 | 남자 | 2500원 |
2 | 손흥민 | 1993-06-12 | 남자 | 1500원 |
3 | 김연아 | 1988-10-16 | 여자 | 2000원 |
병합하는 방법 4가지
how
옵션 값을 지정하여 4가지 방식으로 병합을 할 수 있으며, 각기 다른 결과를 냅니다.
- how : {
left
,right
,outer
,inner
}, - default로 설정된 값은
inner
입니다.
# how='inner' 입니다.
pd.merge(df1, df2)
고객명 | 생년월일 | 성별 | 연봉 | |
---|---|---|---|---|
0 | 박세리 | 1980-01-02 | 여자 | 3000원 |
1 | 이대호 | 1982-02-22 | 남자 | 2500원 |
2 | 손흥민 | 1993-06-12 | 남자 | 1500원 |
3 | 김연아 | 1988-10-16 | 여자 | 2000원 |
pd.merge(df1, df2, how='left')
고객명 | 생년월일 | 성별 | 연봉 | |
---|---|---|---|---|
0 | 박세리 | 1980-01-02 | 여자 | 3000원 |
1 | 이대호 | 1982-02-22 | 남자 | 2500원 |
2 | 손흥민 | 1993-06-12 | 남자 | 1500원 |
3 | 김연아 | 1988-10-16 | 여자 | 2000원 |
4 | 마이클조던 | 1970-03-03 | 남자 | NaN |
pd.merge(df1, df2, how='right')
고객명 | 생년월일 | 성별 | 연봉 | |
---|---|---|---|---|
0 | 김연아 | 1988-10-16 | 여자 | 2000원 |
1 | 박세리 | 1980-01-02 | 여자 | 3000원 |
2 | 손흥민 | 1993-06-12 | 남자 | 1500원 |
3 | 이대호 | 1982-02-22 | 남자 | 2500원 |
4 | 타이거우즈 | NaN | NaN | 3500원 |
pd.merge(df1, df2, how='outer')
고객명 | 생년월일 | 성별 | 연봉 | |
---|---|---|---|---|
0 | 박세리 | 1980-01-02 | 여자 | 3000원 |
1 | 이대호 | 1982-02-22 | 남자 | 2500원 |
2 | 손흥민 | 1993-06-12 | 남자 | 1500원 |
3 | 김연아 | 1988-10-16 | 여자 | 2000원 |
4 | 마이클조던 | 1970-03-03 | 남자 | NaN |
5 | 타이거우즈 | NaN | NaN | 3500원 |
병합하려는 컬럼의 이름이 다른 경우
df1 = pd.DataFrame({
'이름': ['박세리', '이대호', '손흥민', '김연아', '마이클조던'],
'생년월일': ['1980-01-02', '1982-02-22', '1993-06-12', '1988-10-16', '1970-03-03'],
'성별': ['여자', '남자', '남자', '여자', '남자']})
df1
이름 | 생년월일 | 성별 | |
---|---|---|---|
0 | 박세리 | 1980-01-02 | 여자 |
1 | 이대호 | 1982-02-22 | 남자 |
2 | 손흥민 | 1993-06-12 | 남자 |
3 | 김연아 | 1988-10-16 | 여자 |
4 | 마이클조던 | 1970-03-03 | 남자 |
df2 = pd.DataFrame({
'고객명': ['김연아', '박세리', '손흥민', '이대호', '타이거우즈'],
'연봉': ['2000원', '3000원', '1500원', '2500원', '3500원']})
df2
고객명 | 연봉 | |
---|---|---|
0 | 김연아 | 2000원 |
1 | 박세리 | 3000원 |
2 | 손흥민 | 1500원 |
3 | 이대호 | 2500원 |
4 | 타이거우즈 | 3500원 |
left_on
가 right_on
을 지정합니다.
이름과 고객명 컬럼이 모두 drop되지 않고 살아 있음을 확인합니다.
pd.merge(df1, df2, left_on='이름', right_on='고객명')
이름 | 생년월일 | 성별 | 고객명 | 연봉 | |
---|---|---|---|---|---|
0 | 박세리 | 1980-01-02 | 여자 | 박세리 | 3000원 |
1 | 이대호 | 1982-02-22 | 남자 | 이대호 | 2500원 |
2 | 손흥민 | 1993-06-12 | 남자 | 손흥민 | 1500원 |
3 | 김연아 | 1988-10-16 | 여자 | 김연아 | 2000원 |
댓글남기기