Pandas는 두 개 이상의 DataFrame을 하나로 합치는 데이터 병합(merge)이나 연결(concatenate)을 지원한다.
merge
함수를 사용한 DataFrame 병합
merge
함수는 두 데이터프레임의 공통 열 혹은 인덱스를 기준으로 두 개의 테이블을 합친다. 이 때 기준이 되는 열, 행의 데이터를 키(Key)라고 한다.
import pandas as pd
df1 = pd.DataFrame({
'고객번호': [1001, 1002, 1003, 1004, 1005, 1006, 1007],
'이름': ['둘리', '도우너', '또치', '길동', '마이콜', '희동', '영희']
}, columns=['고객번호', '이름'])
df1
|
고객번호 |
이름 |
0 |
1001 |
둘리 |
1 |
1002 |
도우너 |
2 |
1003 |
또치 |
3 |
1004 |
길동 |
4 |
1005 |
마이콜 |
5 |
1006 |
희동 |
6 |
1007 |
영희 |
df2 = pd.DataFrame({
'고객번호': [1001, 1001, 1005, 1006, 1008, 1001],
'금액': [10000, 20000, 15000, 5000, 100000, 30000]
}, columns=['고객번호', '금액'])
df2
|
고객번호 |
금액 |
0 |
1001 |
10000 |
1 |
1001 |
20000 |
2 |
1005 |
15000 |
3 |
1006 |
5000 |
4 |
1008 |
100000 |
5 |
1001 |
30000 |
merge
함수로 위의 두 데이터프레임 df1, df2 를 합치면 공통열인 고객번호
열을 기준으로 데이터를 찾아서 합친다. 이 때 기본적으로는 양쪽 데이터프레임에 모두 키가 존재하는 데이터만 보여주는 inner join 방식을 사용한다.
|
고객번호 |
이름 |
금액 |
0 |
1001 |
둘리 |
10000 |
1 |
1001 |
둘리 |
20000 |
2 |
1001 |
둘리 |
30000 |
3 |
1005 |
마이콜 |
15000 |
4 |
1006 |
희동 |
5000 |
outer join 방식은 키 값이 한쪽에만 있어도 데이터를 보여준다.
pd.merge(df1, df2, how='outer')
|
고객번호 |
이름 |
금액 |
0 |
1001 |
둘리 |
10000.0 |
1 |
1001 |
둘리 |
20000.0 |
2 |
1001 |
둘리 |
30000.0 |
3 |
1002 |
도우너 |
NaN |
4 |
1003 |
또치 |
NaN |
5 |
1004 |
길동 |
NaN |
6 |
1005 |
마이콜 |
15000.0 |
7 |
1006 |
희동 |
5000.0 |
8 |
1007 |
영희 |
NaN |
9 |
1008 |
NaN |
100000.0 |
left, right 방식은 각각 첫번째, 혹은 두번째 데이터프레임의 키 앖을 모두 보여준다.
pd.merge(df1, df2, how='left')
|
고객번호 |
이름 |
금액 |
0 |
1001 |
둘리 |
10000.0 |
1 |
1001 |
둘리 |
20000.0 |
2 |
1001 |
둘리 |
30000.0 |
3 |
1002 |
도우너 |
NaN |
4 |
1003 |
또치 |
NaN |
5 |
1004 |
길동 |
NaN |
6 |
1005 |
마이콜 |
15000.0 |
7 |
1006 |
희동 |
5000.0 |
8 |
1007 |
영희 |
NaN |
pd.merge(df1, df2, how='right')
|
고객번호 |
이름 |
금액 |
0 |
1001 |
둘리 |
10000 |
1 |
1001 |
둘리 |
20000 |
2 |
1001 |
둘리 |
30000 |
3 |
1005 |
마이콜 |
15000 |
4 |
1006 |
희동 |
5000 |
5 |
1008 |
NaN |
100000 |
만약 테이블에 키 값이 같은 데이터가 여러개 있는 경우에는 있을 수 있는 모든 경우의 수를 따져서 조합을 만들어 낸다.
df1 = pd.DataFrame({
'품종': ['setosa', 'setosa', 'virginica', 'virginica'],
'꽃잎길이': [1.4, 1.3, 1.5, 1.3]
}, columns=['품종', '꽃잎길이'])
df1
|
품종 |
꽃잎길이 |
0 |
setosa |
1.4 |
1 |
setosa |
1.3 |
2 |
virginica |
1.5 |
3 |
virginica |
1.3 |
df2 = pd.DataFrame({
'품종': ['setosa', 'virginica', 'virginica', 'versicolor'],
'꽃잎너비': [0.4, 0.3, 0.5, 0.3]},
columns=['품종', '꽃잎너비'])
df2
|
품종 |
꽃잎너비 |
0 |
setosa |
0.4 |
1 |
virginica |
0.3 |
2 |
virginica |
0.5 |
3 |
versicolor |
0.3 |
이 데이터에서 키 값 setosa에 대해 왼쪽 데이터프레임에는 1.4와 1.3 이라는 2개의 데이터, 오른쪽 데이터프레임에는 0.4라는 1개의 데이터가 있으므로 병합된 데이터에는 setosa가 (1.4, 0.4), (1.3, 0.4) 두 개의 데이터가 생긴다. 키값 virginica의 경우에는 왼쪽 데이터프레임에 1.5와 1.3이라는 2개의 데이터, 오른쪽 데이터프레임에 0.3와 0.5라는 2개의 데이터가 있으므로 2개와 2개의 조합에 의해 4가지 값이 생긴다.
|
품종 |
꽃잎길이 |
꽃잎너비 |
0 |
setosa |
1.4 |
0.4 |
1 |
setosa |
1.3 |
0.4 |
2 |
virginica |
1.5 |
0.3 |
3 |
virginica |
1.5 |
0.5 |
4 |
virginica |
1.3 |
0.3 |
5 |
virginica |
1.3 |
0.5 |
두 데이터프레임에서 이름이 같은 열은 모두 키가 된다. 만약 이름이 같아도 키가 되면 안되는 열이 있다면 on
인수로 기준열을 명시해야 한다. 다음 예에서 첫번째 데이터프레임의 데이터는 실제로는 금액을 나타내는 데이터 이고 두번째 데이터프레임의 데이터는 실제로 성별을 나타내는 데이터이므로 이름이 같아도 다른 데이터이다. 따라서 이 열은 기준열이 되면 안된다.
df1 = pd.DataFrame({
'고객명': ['춘향', '춘향', '몽룡'],
'날짜': ['2018-01-01', '2018-01-02', '2018-01-01'],
'데이터': ['20000', '30000', '100000']})
df1
|
고객명 |
날짜 |
데이터 |
0 |
춘향 |
2018-01-01 |
20000 |
1 |
춘향 |
2018-01-02 |
30000 |
2 |
몽룡 |
2018-01-01 |
100000 |
df2 = pd.DataFrame({
'고객명': ['춘향', '몽룡'],
'데이터': ['여자', '남자']})
df2
pd.merge(df1, df2, on='고객명')
|
고객명 |
날짜 |
데이터_x |
데이터_y |
0 |
춘향 |
2018-01-01 |
20000 |
여자 |
1 |
춘향 |
2018-01-02 |
30000 |
여자 |
2 |
몽룡 |
2018-01-01 |
100000 |
남자 |
이 때 기준 열이 아니면서 이름이 같은 열에는 _x
또는 _y
와 같은 접미사가 붙는다.
반대로 키가 되는 기준열의 이름이 두 데이터프레임에서 다르면 left_on
, right_on
인수를 사용하여 기준열을 명시해야 한다.
df1 = pd.DataFrame({
'이름': ['영희', '철수', '철수'],
'성정': [1,2,3]
})
df1
|
이름 |
성정 |
0 |
영희 |
1 |
1 |
철수 |
2 |
2 |
철수 |
3 |
df2 = pd.DataFrame({
'성명': ['영희', '영희', '철수'],
'성적2': [4, 5, 6]})
df2
|
성명 |
성적2 |
0 |
영희 |
4 |
1 |
영희 |
5 |
2 |
철수 |
6 |
pd.merge(df1, df2, left_on='이름', right_on='성명')
|
이름 |
성정 |
성명 |
성적2 |
0 |
영희 |
1 |
영희 |
4 |
1 |
영희 |
1 |
영희 |
5 |
2 |
철수 |
2 |
철수 |
6 |
3 |
철수 |
3 |
철수 |
6 |
일반 데이터 열이 아닌 인덱스를 기준열로 사용하여면 left_index
또는 right_index
인수를 True
로 설정한다.
df1 = pd.DataFrame({
'도시': ['서울', '서울', '서울', '부산', '부산'],
'연도': [2000, 2005, 2010, 2000, 2005],
'인구': [9853972, 9762546, 9631482, 3655437, 3512547]})
df1
|
도시 |
연도 |
인구 |
0 |
서울 |
2000 |
9853972 |
1 |
서울 |
2005 |
9762546 |
2 |
서울 |
2010 |
9631482 |
3 |
부산 |
2000 |
3655437 |
4 |
부산 |
2005 |
3512547 |
import numpy as np
df2 = pd.DataFrame(
np.arange(12).reshape((6, 2)),
index=[['부산', '부산', '서울', '서울', '서울', '서울'],
[2000, 2005, 2000, 2005, 2010, 2015]],
columns=['데이터1', '데이터2'])
df2
|
|
데이터1 |
데이터2 |
부산 |
2000 |
0 |
1 |
2005 |
2 |
3 |
서울 |
2000 |
4 |
5 |
2005 |
6 |
7 |
2010 |
8 |
9 |
2015 |
10 |
11 |
pd.merge(df1, df2, left_on=['도시', '연도'], right_index=True)
|
도시 |
연도 |
인구 |
데이터1 |
데이터2 |
0 |
서울 |
2000 |
9853972 |
4 |
5 |
1 |
서울 |
2005 |
9762546 |
6 |
7 |
2 |
서울 |
2010 |
9631482 |
8 |
9 |
3 |
부산 |
2000 |
3655437 |
0 |
1 |
4 |
부산 |
2005 |
3512547 |
2 |
3 |
df1 = pd.DataFrame(
[[1., 2.], [3., 4.], [5., 6.]],
index=['a', 'c', 'e'],
columns=['서울', '부산'])
df1
|
서울 |
부산 |
a |
1.0 |
2.0 |
c |
3.0 |
4.0 |
e |
5.0 |
6.0 |
df2 = pd.DataFrame(
[[7., 8.], [9., 10.], [11., 12.], [13, 14]],
index=['b', 'c', 'd', 'e'],
columns=['대구', '광주'])
df2
|
대구 |
광주 |
b |
7.0 |
8.0 |
c |
9.0 |
10.0 |
d |
11.0 |
12.0 |
e |
13.0 |
14.0 |
pd.merge(df1, df2, how='outer', left_index=True, right_index=True)
|
서울 |
부산 |
대구 |
광주 |
a |
1.0 |
2.0 |
NaN |
NaN |
b |
NaN |
NaN |
7.0 |
8.0 |
c |
3.0 |
4.0 |
9.0 |
10.0 |
d |
NaN |
NaN |
11.0 |
12.0 |
e |
5.0 |
6.0 |
13.0 |
14.0 |
join 매서드
merge
명령어 대신 join
매서드를 사용할 수도 있다.
df1.join(df2, how='outer')
|
서울 |
부산 |
대구 |
광주 |
a |
1.0 |
2.0 |
NaN |
NaN |
b |
NaN |
NaN |
7.0 |
8.0 |
c |
3.0 |
4.0 |
9.0 |
10.0 |
d |
NaN |
NaN |
11.0 |
12.0 |
e |
5.0 |
6.0 |
13.0 |
14.0 |
concat
함수를 사용한 데이터 연결
concat
함수를 사용하면 기준 열(key column)을 사용하지 않고 단순히 데이터를 연결(concatenate)한다.
기본적으로는 위/아래로 데이터 행을 연결한다. 단순히 두 시리즈나 데이터프레임을 연결하기 때문에 인덱스 값이 중복될 수 있다.
s1 = pd.Series([0,1], index=['A','B'])
s2 = pd.Series([2,3,4], index=['A','B','C'])
A 0
B 1
A 2
B 3
C 4
dtype: int64
내부적으로 기본값은 axis=0
이기 때문에 만약 옆으로 데이터 열을 연결하고 싶으면 axis=1
로 인수를 설정한다.
df1 = pd.DataFrame(
np.arange(6).reshape(3, 2),
index=['a', 'b', 'c'],
columns=['데이터1', '데이터2'])
df1
|
데이터1 |
데이터2 |
a |
0 |
1 |
b |
2 |
3 |
c |
4 |
5 |
df2 = pd.DataFrame(
5 + np.arange(4).reshape(2, 2),
index=['a', 'c'],
columns=['데이터3', '데이터4'])
df2
pd.concat([df1, df2], axis=1)
|
데이터1 |
데이터2 |
데이터3 |
데이터4 |
a |
0 |
1 |
5.0 |
6.0 |
b |
2 |
3 |
NaN |
NaN |
c |
4 |
5 |
7.0 |
8.0 |
출처 : 데이터사이언스 스쿨(http://datascienceschool.net)