판다스에서는 시리즈나 데이터프레임을 다루기 편하게 하기 위해 여러 함수들을 제공하고 있다.
그 중, 여러 개의 데이터프레임이나 시리즈를 합치는 기능은 빈번히 사용되는 기능들 중 하나이다.
1. concat()
첫 번째는 concat() 메서드이다. concat() 메서드는 이름 그대로 데이터프레임 또는 시리즈를 연결하는 기능이다. 아래 예시처럼 서로 다른 두 데이터프레임을 합칠 수 있다.
df1 = pd.DataFrame(
{
"A": ["A0", "A1", "A2", "A3"],
"B": ["B0", "B1", "B2", "B3"],
"C": ["C0", "C1", "C2", "C3"],
"D": ["D0", "D1", "D2", "D3"],
},
index=[0,1,2,3]
}
df2 = pd.DataFrame(
{
"A": ["A4", "A5", "A6", "A7"],
"B": ["B4", "B5", "B6", "B7"],
"C": ["C4", "C5", "C6", "C7"],
"D": ["D4", "D5", "D6", "D7"],
},
index=[4,5,6,7]
)
frames = pd.concat([df1, df2])
frames
=>
A B C D
0 A0 B0 C0 D0
1 A1 B1 C1 D1
2 A2 B2 C2 D2
3 A3 B3 C3 D3
4 A4 B4 C4 D4
5 A5 B5 C5 D5
6 A6 B6 C6 D6
7 A7 B7 C7 D7
위의 경우처럼 인덱스를 설정해준 경우, 데이터프레임의 shape이 인덱스에 맞지 않는다면(위의 경우에서는 row 4개), concat() 호출 시 오류가 난다. 그러나 설정해주지 않는다면 오류가 나지 않고 연결된다. ignore_index = True로 설정해서 기존 인덱스를 무시하고 연결해줄 수 있다.
# 인덱스를 설정한 경우
df1 = pd.DataFrame(
{
"A": ["A0", "A1", "A2", "A3"],
"B": ["B0", "B1", "B2", "B3"],
"C": ["C0", "C1", "C2", "C3"],
"D": ["D0", "D1", "D2", "D3"],
},
index=[0,1,2,3]
)
df2 = pd.DataFrame(
{
"A": ["A4", "A5", "A6", "A7","A8"],
"B": ["B4", "B5", "B6", "B7","B8"],
"C": ["C4", "C5", "C6", "C7","C8"],
"D": ["D4", "D5", "D6", "D7","D8"],
},
index=[4,5,6,7]
)
frames = pd.concat([df1, df2])
frames
=>
...
ValueError: Shape of passed values is (5, 4), indices imply (4, 4)
# 인덱스를 설정하지 않은 경우
df1 = pd.DataFrame(
{
"A": ["A0", "A1", "A2", "A3"],
"B": ["B0", "B1", "B2", "B3"],
"C": ["C0", "C1", "C2", "C3"],
"D": ["D0", "D1", "D2", "D3"],
}
)
df2 = pd.DataFrame(
{
"A": ["A4", "A5", "A6", "A7","A8"],
"B": ["B4", "B5", "B6", "B7","B8"],
"C": ["C4", "C5", "C6", "C7","C8"],
"D": ["D4", "D5", "D6", "D7","D8"],
}
)
frames = pd.concat([df1, df2], ignore_index=True)
frames
=>
A B C D
0 A0 B0 C0 D0
1 A1 B1 C1 D1
2 A2 B2 C2 D2
3 A3 B3 C3 D3
4 A4 B4 C4 D4
5 A5 B5 C5 D5
6 A6 B6 C6 D6
7 A7 B7 C7 D7
8 A8 B8 C8 D8
# df2의 기존 인덱스인 0,1,2,3,4 대신 4,5,6,7,8이 인덱스로 설정되었다.
concat() 메서드는 데이터프레임 뿐만 아니라 시리즈도 연결할 수 있다. 그 대신 시리즈 객체를 데이터프레임으로 변경하고, 전치시켜주는 과정을 거쳐야한다.
s1 = pd.Series(["A9","B9","C9","D9"], index=['A','B','C','D'])
frames = pd.concat([frames, s1.to_frame().T], ignore_index=True)
frames
=>
A B C D
0 A0 B0 C0 D0
1 A1 B1 C1 D1
2 A2 B2 C2 D2
3 A3 B3 C3 D3
4 A4 B4 C4 D4
5 A5 B5 C5 D5
6 A6 B6 C6 D6
7 A7 B7 C7 D7
8 A8 B8 C8 D8
9 A9 B9 C9 D9
concat() 메서드는 파라미터 axis를 설정하여 행 방향으로 또는 열 방향으로 합칠 수 있다. axis의 기본값은 0으로, 기본적으로는 행 방향으로 합친다. 그러나 axis=1로 설정하여 열 방향으로 합치는 경우도 가능하다.
df1 = pd.DataFrame(
{
"A": ["A0", "A1", "A2", "A3"],
"B": ["B0", "B1", "B2", "B3"],
"C": ["C0", "C1", "C2", "C3"],
"D": ["D0", "D1", "D2", "D3"],
}
)
df2 = pd.DataFrame(
{
"E": ["E0","E1","E2","E3"],
"F": ["F0","F1","F2","F3"],
}
)
frames = pd.concat([df1, df2], axis=1)
frames
=>
A B C D E F
0 A0 B0 C0 D0 E0 F0
1 A1 B1 C1 D1 E1 F1
2 A2 B2 C2 D2 E2 F2
3 A3 B3 C3 D3 E3 F3
열 방향으로 합칠 때에는 시리즈 객체를 바로 합쳐줄 수 있다.
s1 = pd.Series(['G0','G1','G2','G3'])
frames = pd.concat([frames, s1], axis=1)
frames
=>
A B C D E F 0
0 A0 B0 C0 D0 E0 F0 G0
1 A1 B1 C1 D1 E1 F1 G1
2 A2 B2 C2 D2 E2 F2 G2
3 A3 B3 C3 D3 E3 F3 G3
이 외에도 concat() 메서드는 여러가지 파라미터를 가지고 있다.
pd.concat(
objs,
axis=0,
join="outer",
ignore_index=False,
keys=None,
levels=None,
names=None,
verify_integrity=False,
copy=True,
)
# objs: 데이터프레임 또는 시리즈의 시퀀스
# axis: 합칠 축의 방향
# join: {'inner','outer'}. 기본값은 'outer'이고, 합집합으로 합침. 'inner'는 교집합으로 합침
# ignore_index: True로 설정할 시, 기존 객체의 인덱스 무시
# keys: 시퀀스를 받고 계층을 가진 멀티 인덱스를 생성한다.
# levels: 시퀀스를 받고 멀티 인덱스를 생성한다.
2. merge()
두 번째는 merge() 메서드이다. 판다스의 merge() 메서드 또한 concat()과 마찬가지로 데이터프레임 또는 시리즈를 병합할 수 있는 기능이다. concat()과의 차이점이라면, merge()는 시리즈 또는 데이터프레임 객체를 대상으로 join을 실행한다. SQL의 개념과 유사하다.
아래는 시리즈를 key로 merge()를 수행한 결과이다. 파라미터 on = 'key'로 설정한 결과이다.
left = pd.DataFrame(
{
"key": ["K0", "K1", "K2", "K3"],
"A": ["A0", "A1", "A2", "A3"],
"B": ["B0", "B1", "B2", "B3"],
}
)
right = pd.DataFrame(
{
"key": ["K0", "K1", "K2", "K3"],
"C": ["C0", "C1", "C2", "C3"],
"D": ["D0", "D1", "D2", "D3"],
}
)
result = pd.merge(left, right, on="key")
result
=>
key A B C D
0 K0 A0 B0 C0 D0
1 K1 A1 B1 C1 D1
2 K2 A2 B2 C2 D2
3 K3 A3 B3 C3 D3
# 'key' 컬럼을 중심으로 데이터프레임이 합쳐졌다.
시리즈 대신 데이터프레임을 key로 사용할 수도 있다. 파라미터 on = ['key1', 'key2']로 설정하였다.
left = pd.DataFrame(
{
"key1": ["K0", "K0", "K1", "K2"],
"key2": ["K0", "K1", "K0", "K1"],
"A": ["A0", "A1", "A2", "A3"],
"B": ["B0", "B1", "B2", "B3"],
}
)
right = pd.DataFrame(
{
"key1": ["K0", "K1", "K1", "K2"],
"key2": ["K0", "K0", "K0", "K0"],
"C": ["C0", "C1", "C2", "C3"],
"D": ["D0", "D1", "D2", "D3"],
}
)
result = pd.merge(left, right, on=["key1", "key2"])
result
=>
key1 key2 A B C D
0 K0 K0 A0 B0 C0 D0
1 K1 K0 A2 B2 C1 D1
2 K1 K0 A2 B2 C2 D2
# 'key1'과 'key2' 컬럼을 중심으로 합쳐졌다.
merge() 메서드에는 다양한 파라미터가 존재한다.
left, right는 각각 merge()의 대상이 되는 데이터프레임이다.
pd.merge(
left,
right,
how="inner",
on=None,
left_on=None,
right_on=None,
left_index=False,
right_index=False,
sort=True,
suffixes=("_x", "_y"),
copy=True,
indicator=False,
validate=None,
)
# how: join 방식을 말한다. {'left','right','outer','inner','cross'}가 있다.
# on: join의 기준이 되는 column 또는 index이다.
# sort: key를 기준으로 데이터프레임을 사전순으로 정렬한다.
# validate: string 값을 전달하면 merge()가 특정 타입인지 체크한다.
"one-to-one" or "1:1" / "one-to-many" or "1:m" / "many-to-one" or "m:1" / "many-to-many" or "m:m"
참고자료
[1] "Merge, join, concatenate and compare", Pandas, https://pandas.pydata.org/docs/user_guide/merging.html
'Python > Pandas' 카테고리의 다른 글
[Pandas] 판다스 결측치 처리 (2) | 2023.06.19 |
---|---|
[Pandas] 판다스 인덱싱 (loc, iloc) (0) | 2023.02.04 |
[Pandas] 판다스 기본 함수들 (1) | 2023.02.03 |
[Pandas] 판다스(Pandas)와 데이터 구조 (1) | 2023.01.31 |