Python_Pandas_05(DataFrame 합치기)
데이터프레임 합치기 : 두개 이상의 DataFrame을 합쳐 하나의 DataFrame으로 만든다.
- 수직결합
- 단순결합으로 여러개의 DataFrame들의 같은 컬럼끼리 수직으로 합친다.
- 수평결합
- 연관성 있는 여러 데이터를 하나로 합쳐서 조회하는 JOIN 처리를 한다.
- JOIN은 합치려는 DataFrame들의 index 나 특정 컬럼의 값이 같은 행 끼리 합친다.
데이터셋 읽기
- stocks_2016.csv, stocks_2017.csv, stocks_2018.csv : 년도별 보유 주식
- stocks_info.csv : 주식 정보
import pandas as pd
pd.read_csv("data/stocks_2016.csv")
pd.read_csv("data/stocks_2017.csv")
pd.read_csv("data/stocks_2018.csv")
pd.read_csv("data/stocks_info.csv")
위와 같이 하나씩 pd.read_csv로 한다면 코드의 가독성이 떨어질 수 있다.
아래와 같이 여러개의 데이터셋을 한번에 읽어준다.
# 파일명이 다 제각각 다른경우(패턴이 없는 경우)는 리스트에 전체 경로를 다 넣는다.
["data/stocks_2016.csv", "data/stocks_2017.csv",
"data/stocks_2018.csv", "data/stocks_info.csv"]
파일들이 stocks_ 뒤에 글자로 시작하기에 다음과 같이 파일들을 읽는다.
files = ["2016", "2017", "2018", "info"]
stock_2016, stock_2017, stock_2018, stock_info = [pd.read_csv(f"data/stocks_{file}.csv") for file in files]
stock_2016.shape, stock_2017.shape, stock_2018.shape, stock_info.shape
파일들을 조회해 본다.
from glob import glob # 특정 디렉토리안의 파일들의 경로를 조회
## 파일명: * : 0개이상의 모든 글자.
## 디렉토리: ** : 모든 하위 디렉토리.
[pd.read_csv(file) for file in glob("data/stock*.csv")]
- "data/*.csv" -> data 디렉토리 바로 아래있는 파일들중 확장자가 csv인 파일들의 경로
- "data/**/*.csv" -> data 디렉토리 + 그 하위 디렉토리에 있는 모든 csv파일.
stock_2018 # 파일 확인
stock_info
concat() 이용
- 수직, 수평 결합 모두 지원한다.
- 하나의 데이터셋을 여러 DataFrame으로 나눈 것을 하나의 DataFrame으로 합칠 때 사용한다.
- 수직 결합 (행이 늘어나도록 합친다.)
- 컬럼명이 같은 열끼리 합친다.
- 같은 column 명이 없는 열들도 결과 DataFrame에 들어간다.(default)
- full outer join개념
- 수평결합 (열이 늘어나도록 합친다.)
- index명이 같은 행 끼리 합친다. (equi-join)
- 같은 index명이 없는 행들도 결과 DataFrame에 들어간다.(default)
- full outer join
pd.concat(objs, [, key=리스트]), axis=0, join='outer' )
- 매개변수
- objs: 합칠 DataFrame들을 리스트로 전달
- keys=[] 를 이용해 합친 행들을 구분하기 위한 다중 인덱스 처리
- axis
- 0 또는 index : 수직결합
- 1 또는 columns : 수평결합
- join: 합치는 방식으로 다음 문자열을 값으로 설정한다.
- 'outer'(기본값): full outer join
- 'inner': inner join (동일한 index명, column명 끼리 합친다.)
조인(join)
- 여러 데이터프레임에 흩어져 있는 정보 중 필요한 정보만 모아서 결합하기 위한 것.
- 두개 이상의 데이터프레임을 특정 컬럼(열)의 값이 같은 행 끼리 수평 결합하는 것.
- Inner Join, Left Outer Join, Right Outer Join, Full Outer Join
# default 방향: 0 -> 수직 결합. 같은 컬럼명끼리 합친다.
stocks = pd.concat([stock_2016, stock_2017, stock_2018])
stocks.shape
stocks.head()
ignore_index=True -> index 이름을 버리고 index가 0번 ~ n번까지 이름이 붙는다.
stocks2 = pd.concat([stock_2016, stock_2017, stock_2018],
ignore_index=True # index이름은 합칠때 무시.(버린다.)
)
stocks2
DataFrame을 구분할 수 있는 index 추가
stocks3 = pd.concat([stock_2016, stock_2017, stock_2018],
keys=["2016년", "2017년", "2018년"] # 각 DataFrame을 구분할 수 있는 index를 추가. => Multi index
)
stocks3
- multi index: 컬럼명이나 index 명이 여러개의 값으로 구성된 것.
- level : 컬럼을 구성하는 값들의 단위(단계)를 level이라고 함.
- 밖에서 안으로 들어오는 방향으로 0, 1, 2 level이 됨. (반대방향은 음수 index)
- level_0 | level_1
- 2016 | 0
stocks3.loc['2016년'] # 멀티 인덱스 -> level 0 기준 조회
stocks3.loc[('2016년', 0)] # level 0, level 1 묶어서 조회 -> 튜플로 묶어서 전달.
# 멀티 index 행/컬럼을 조회하는 메소드
stocks3.xs(0, # 조회할 컬럼/행이름
axis=0, # 0: 행조회, 1: 열조회
level=1 # 조회할 이름의 level 위치.
)
수평조인
### 행기준(수평)으로 합치기 -> index name이 같은 행끼리 합친다.
stocks4 = pd.concat([stock_2016, stock_2017, stock_2018],
axis=1)
stocks4
각 DataFrame 값 확인, # 숫자 -> DataFrame이 가진 index의 값
stock_2016 # 0, 1, 2
stock_2017 # 0, 1, 2, 3, 4, 5
stock_2018 # 0, 1, 2
stock5 = pd.concat([stock_2016, stock_2017, stock_2018],
axis=1, # 수평방향으로 합치기.
join="inner" # inner join => 같은 index이름끼리만 합친다.
# , ignore_index=True, # 수평->컬럼명을 무시
, keys=['2016년', '2017년', '2018년'] # 컬럼: ㄴmulti index
)
stock5
stock5['2016년'] # level 0 기준으로 조회
stock5[['2016년', '2018년']]
stock5[('2016년', 'Shares')] # (Level0, Level1) -> tuple로 묶는다.
stock5.xs('Shares', level=-1, axis=1)
조인을 통한 DataFrame 합치기
- 연관성있는 둘 이상의 DataFrame을 하나로 합친다.
- ex) 고객과 주문정보, 교수와 수업정보, 직원과 부서정보
- join()
- 2개 이상의 DataFrame을 조인할 때 사용
- merge()
- 2개의 DataFrame의 조인만 지원
join()
dataframe객체.join(others, how='left', lsuffix='', rsuffix='')
- df_A.join(df_b), df_A.join([df_b, df_c, df_d])
- 두개 이상의 DataFrame들을 조인 할 수 있다.
- 조인 기준: index가 같은 값인 행끼리 합친다. (equi-join)
- 조인 기본 방식: Left Outer Join
- 매개변수
- lsuffix, rsuffix
- 조인 대상 DataFrame에 같은 이름의 컬럼이 있으면 에러 발생.
- 같은 이름이 있는 경우 붙일 접미어 지정
- how :조인방식. 'left', 'right', 'outer', 'inner'. left가 기본
# stock_info: Symbol
# stock_2018: Symbol
stock_info.join(stock_2018, lsuffix='_info')
# stock_info: Symbol
# stock_2018: Symbol
## Symbol을 index로 변경
join_result1 = stock_info.set_index("Symbol").join(stock_2018.set_index("Symbol"))
join_result1
inner join
join_result2 = stock_info.set_index("Symbol").join(stock_2018.set_index("Symbol"),
how="inner")
join_result2
3개의 DataFrame join
stock_info.set_index("Symbol").join([stock_2016.set_index("Symbol").add_suffix('_2016'),
stock_2017.set_index("Symbol").add_suffix('_2017')]
)
column명 뒤에 접미어 붙이기
stock_2016.set_index("Symbol").add_suffix("_2016") # 컬럼명 뒤에 접미어를 붙여준다. (add_prefix() : 접두어)
merge()
df_a.merge(df_b)
- 두개의 DataFrame간의 조인만 가능하다.
- 조인 기준
- 같은 컬럼명을 기준으로 equi-join을 하는 것이 기본이다.
- 조인기준을 다양하게 정할 수 있다.
- 컬럼, index등을 기준으로 같은 행끼리 join 하도록 설정할 수 있다.
- 조인 기본 방식
- inner join
- how 매개변수를 이용해 변경이 가능하다.
dataframe.merge(합칠dataframe, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False)
- 매개변수
- on : 같은 컬럼명이 여러개일때 join 대상 컬럼을 선택
- right_on, left_on : 조인할 때 사용할 왼쪽,오른쪽 Dataframe의 컬럼명.
- left_index, right_index: 조인 할때 index를 사용할 경우 True로 지정
- how : 조인 방식. 'left', 'right', 'outer', 'inner'. 기본: inner
- suffixes: 두 DataFrame에 같은 이름의 컬럼명이 있을 경우 구분을 위해 붙인 접미어를 리스트로 설정
- 생략시 x, y를 붙인다.
# default: 같은이름의 컬럼명을 기준으로 join
stock_info.merge(stock_2016,
how='left' ## default: inner
)
stock2016 = stock_2016.set_index("Symbol")
stock2016
# stock_info: Symbol - 컬럼, stock2016: Symbol - index
stock_info.merge(stock2016
, left_on="Symbol" # 왼쪽 DF(stock_info)의 join 컬럼을 지정.
, right_index=True # 오른쪽 DF(stock2016)의 index를 join 기준으로 사용.
)
# 동일한 이름의 컬럼이 여러개이고 이중 join 기준컬럼은 일부를 사용할 경우.
stock_2016.merge(stock_2018, on="Symbol",
suffixes=["_2016", "_2018"])
- 하나의 데이터셋을 어떤 특정행 또튼 특정열을 기준으로 단순해 분리 한 경우를 합치는 경우 concat() 사용
- 수직 결합일 경우는 concat()을 사용해야 한다.
- 서로 연관성 있는 다른 데이터셋을 결합해서 보는 경우 join(), merge()를 사용한다. (Join)
- 두 개 이상의 DataFrame을 조인할 때는 하는 경우 : join() 사용
- 두개의 DataFrame을 조인할 때는 merge() 를 사용한다. => 컨트롤이 편하다.
TODO 문제
# 1 data/customer.csv, data/order.csv, data/qna.csv 를 DataFrame으로 읽으시오.
file_names = ["customer", "order", "qna"]
customer, order, qna = [pd.read_csv(f"data/{name}.csv") for name in file_names]
customer.shape, order.shape, qna.shape
# 2 TODO1에서 읽은 세개의 데이터셋의 정보를 확인하세요.
print(customer.columns)
print(order.columns)
print(qna.columns)
# 3 customer DataFrame과 order DataFrame을 고객정보는 모두 나오도록 join 하세요.
result = customer.merge(order, left_on="id", right_on="cust_id", how='left').drop(columns='cust_id')
result
# 4 customer DataFrame의 index를 id컬럼으로 변경.
customer.set_index('id', inplace=True)
customer
# 5 4에서 만든 customer DataFrame과 qna DataFrame을 inner join 하세요.
## join() - index name 기준
customer.join(qna.set_index('cust_id'), how="inner")
merge() 할 경우
## merge()
customer.merge(qna, left_index=True, right_on="cust_id", how="inner")
# 6. 세개의 DataFrame을 고객정보는 모두 나오도록 join 하세요.
customer.join([order.set_index('cust_id'),
qna.set_index('cust_id')
], how='left')