[Programming] DataFrmae - Join
- 데이터를 병합하는 방법은 다양하나, 큰 데이터를 다룰 때에는 어떤 방식이 가장 효율적인지 비교할 필요가 있다.
- 한 칼럼에 대해 병합할 경우
pd.concat
과pd.merge
함수 중 어떤 함수가 빠른 속도로 진행이 되는지 비교하였다.
pd.concat(objs)
pd.concat()
은 데이터프레임을 물리적으로 붙이는 함수이다.- 데이터프레임과 데이터프레임, 데이터프레임과 시리즈, 시리즈와 시리즈를 병합할 수 있다.
- 옵션은 다음과 같다.
pandas.concat(objs, axis=0, join='outer', ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False, sort=False, copy=True)
- 자주 사용하는 옵션으로는 axis, join, ignore_index 등이 있다.
- axis: 0의 경우 행방향으로(위 아래 병합), 1의 경우 열방향으로 결합이 된다.
- join: {‘inner’, ‘outer’} 중 선택이 가능하다. 디폴트 값은 outer이다.
- ignore_index: 인덱스에 따라 이어붙일 것인가를 선택할 수 있다. 만약 인덱스 번호가 다를 경우 ignore_index = True를 줘서 재배열한다.
- 디폴트 값은 다음과 같다: 행단위로 병합(axis=0)이 되며, 인덱스는 중복되어(ignore_index=False) 표시한다.
import pandas as pd
df1 = pd.DataFrame({'a':['a0','a1','a2','a3'],
'b':['b0','b1','b2','b3'],
'c':['c0','c1','c2','c3']},
index = [0,1,2,3])
df2 = pd.DataFrame({'a':['a0','a1','a2','a3','a4'],
'd':['d10','d11','d12','d13', 'd14'],
'e':['e10','e11','e12','e13', 'e14'],
'f':['f10','f11','f12','f13', 'f14']},
index = [2,3,4,5,6])
pd.concat([df1,df2]) # 행단위로 병합되며, 인덱스가 중복되어 표시된다.
a | b | c | d | e | f | |
---|---|---|---|---|---|---|
0 | a0 | b0 | c0 | NaN | NaN | NaN |
1 | a1 | b1 | c1 | NaN | NaN | NaN |
2 | a2 | b2 | c2 | NaN | NaN | NaN |
3 | a3 | b3 | c3 | NaN | NaN | NaN |
2 | a0 | NaN | NaN | d10 | e10 | f10 |
3 | a1 | NaN | NaN | d11 | e11 | f11 |
4 | a2 | NaN | NaN | d12 | e12 | f12 |
5 | a3 | NaN | NaN | d13 | e13 | f13 |
6 | a4 | NaN | NaN | d14 | e14 | f14 |
- axis=1을 설정함으로써 열 단위로 병합하게 되고, ignore_index=True로 설정하여 병합 후 인덱스가 재배열된다.
pd.concat([df1,df2], axis=1, ignore_index=True)
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|---|
0 | a0 | b0 | c0 | NaN | NaN | NaN | NaN |
1 | a1 | b1 | c1 | NaN | NaN | NaN | NaN |
2 | a2 | b2 | c2 | a0 | d10 | e10 | f10 |
3 | a3 | b3 | c3 | a1 | d11 | e11 | f11 |
4 | NaN | NaN | NaN | a2 | d12 | e12 | f12 |
5 | NaN | NaN | NaN | a3 | d13 | e13 | f13 |
6 | NaN | NaN | NaN | a4 | d14 | e14 | f14 |
- join=’inner’을 설정하면 두 데이터프레임의 공통된 부분만 출력된다. 현재는 index 기준으로 병합이 되었다.
pd.concat([df1,df2], axis=1, join='inner') # 인덱스가 동일한 행
a | b | c | a | d | e | f | |
---|---|---|---|---|---|---|---|
2 | a2 | b2 | c2 | a0 | d10 | e10 | f10 |
3 | a3 | b3 | c3 | a1 | d11 | e11 | f11 |
pd.concat([df1,df2], axis=0, join='inner') # 칼럼명이 동일한 열
a | |
---|---|
0 | a0 |
1 | a1 |
2 | a2 |
3 | a3 |
2 | a0 |
3 | a1 |
4 | a2 |
5 | a3 |
6 | a4 |
- 시리즈를 병합할 수도 있다.
- 시리즈를 생성할 때 name을 등록해주면 칼럼명으로 사용할 수 있다.
series = pd.Series(['a00','a01','a02'], name = 'aa', index = [3,4,5])
pd.concat([df2, series], axis=1)
a | d | e | f | aa | |
---|---|---|---|---|---|
2 | a0 | d10 | e10 | f10 | NaN |
3 | a1 | d11 | e11 | f11 | a00 |
4 | a2 | d12 | e12 | f12 | a01 |
5 | a3 | d13 | e13 | f13 | a02 |
6 | a4 | d14 | e14 | f14 | NaN |
data.merge(right)
pd.merge()
는 두 데이터프레임을 고유값 기준으로 병합할 때 사용한다.- 옵션은 다음과 같다.
DataFrame.merge(right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=False, suffixes=('_x', '_y'), copy=True, indicator=False, validate=None)
import pandas as pd
df1 = pd.DataFrame({'a':['a0','a1','a2'],
'b':['b0','b1','b2'],
'c':['a0','a1','a2']},
index = [0,1,2])
df2 = pd.DataFrame({'a':['a0','a2','a5','a0'],
'd':['d10','d11','d12','d13'],
'e':['e10','e11','e12','e13']},
index = [2,3,4,5])
pd.merge(df1, df2) # 공통된 key값에 대한 inner join이 수행된다.
a | b | c | d | e | |
---|---|---|---|---|---|
0 | a0 | b0 | a0 | d10 | e10 |
1 | a0 | b0 | a0 | d13 | e13 |
2 | a2 | b2 | a2 | d11 | e11 |
- 칼럼명이 다를 경우 병합할 key 칼럼을 지정할 수 있다.
pd.merge(df1, df2, left_on='c', right_on='a')
a_x | b | c | a_y | d | e | |
---|---|---|---|---|---|---|
0 | a0 | b0 | a0 | a0 | d10 | e10 |
1 | a0 | b0 | a0 | a0 | d13 | e13 |
2 | a2 | b2 | a2 | a2 | d11 | e11 |
- 기본적으로는 inner join이 수행되나 outer join으로 병합할 수도 있다.
pd.merge(df1, df2, how='outer')
a | b | c | d | e | |
---|---|---|---|---|---|
0 | a0 | b0 | a0 | d10 | e10 |
1 | a0 | b0 | a0 | d13 | e13 |
2 | a1 | b1 | a1 | NaN | NaN |
3 | a2 | b2 | a2 | d11 | e11 |
4 | a5 | NaN | NaN | d12 | e12 |
속도 비교
- 다음과 같은 코드를 통해 수행 속도를 비교하였다.
import time
startTime = time.perf_counter()
# 실행 코드 #
print(time.perf_counter() - startTime)
데이터 사이즈 | 실행 코드 | 수행 속도 |
---|---|---|
(50, 2), (50, 2) | pd.concat | 0.003 |
(50, 2), (50, 2) | pd.merge | 0.006 |
(50000, 2), (50000, 2) | pd.concat | 0.009 |
(50000, 2), (50000, 2) | pd.merge | 0.137 |
- 비교에 사용한 데이터는
pd.DataFrame(np.random.randint(1000, size=(N,2)))
이며 첫번째 칼럼에 대해 결합을 시도하였다. - 데이터의 사이즈(
N
)와 상관없이concat
함수의 속도가 더 우세하다는 것을 확인하였다. - 다만 이는 데이터 특성에 따라, 데이터 크기에 따라 상이할 수 있으므로 일반화하기는 어려우나, 타 블로그의 글을 참고하더라도
concat
을 권장하는 분들이 많다는 것을 알 수 있다. -
참고로, 행만 추가할 경우, dict 타입 데이터를 생성 후
append
나 list 타입 데이터 생성 후extend
하는 방식이 보다 빠르게 처리된다고 한다. - 참고문서
댓글남기기