먼저 concat 메서드에 대해 알아보자.
concat메서드는 여러 개의 데이터프레임을 연결하는 메서드이다. 두 개의 데이터프레임을 연결할 때는 append를 써도 된다.
실습에서 사용할 데이터를 가져와서 확인해준다.
import pandas as pd
df1 = pd.read_csv('../data/concat_1.csv')
df2 = pd.read_csv('../data/concat_2.csv')
df3 = pd.read_csv('../data/concat_3.csv')
print(df1.head(), '\n', df2.head(), '\n', df3.head())
A B C D
0 a0 b0 c0 d0
1 a1 b1 c1 d1
2 a2 b2 c2 d2
3 a3 b3 c3 d3
A B C D
0 a4 b4 c4 d4
1 a5 b5 c5 d5
2 a6 b6 c6 d6
3 a7 b7 c7 d7
A B C D
0 a8 b8 c8 d8
1 a9 b9 c9 d9
2 a10 b10 c10 d10
3 a11 b11 c11 d11
가져온 데이터프레임들을 concat 메서드로 연결시킬 수 있다.
row_concat = pd.concat([df1, df2, df3])
print(row_concat)
A B C D
0 a0 b0 c0 d0
1 a1 b1 c1 d1
2 a2 b2 c2 d2
3 a3 b3 c3 d3
0 a4 b4 c4 d4
1 a5 b5 c5 d5
2 a6 b6 c6 d6
3 a7 b7 c7 d7
0 a8 b8 c8 d8
1 a9 b9 c9 d9
2 a10 b10 c10 d10
3 a11 b11 c11 d11
3개의 데이터프레임이 모두 같은 열 이름을 가지고 있으므로 행방향으로 연결된다.
그렇다면 시리즈를 데이터프레임에 연결하면 어떻게 될까?
새로운 시리즈를 생성하여 합쳐보자.
new_row_series = pd.Series(['n1', 'n2', 'n3', 'n4']) # 리스트를 시리즈로 변경하여 새로운 시리즈를 생성.
print(pd.concat([df1, new_row_series]))
A B C D 0
0 a0 b0 c0 d0 NaN
1 a1 b1 c1 d1 NaN
2 a2 b2 c2 d2 NaN
3 a3 b3 c3 d3 NaN
0 NaN NaN NaN NaN n1
1 NaN NaN NaN NaN n2
2 NaN NaN NaN NaN n3
3 NaN NaN NaN NaN n4
concat 메소드로 데이터프레임과 시리즈를 연결하면 시리즈는 새로운 열로 추가가 된다.
시리즈가 열로 추가되는 이유는 시리즈는 열 이름이 없기 때문에 행으로 추가할 수가 없기 때문이다.
이때 NaN은 누락값이다.
데이터프레임끼리의 연결도 가능하다.
행 1개로 구성된 데이터프레임을 생성하여 연결해보자.
new_row_df = pd.DataFrame([['n1', 'n2', 'n3', 'n4']], columns=['A', 'B', 'C', 'D'])
print(new_row_df, '\n')
print(pd.concat([df1, new_row_df]))
A B C D
0 n1 n2 n3 n4
A B C D
0 a0 b0 c0 d0
1 a1 b1 c1 d1
2 a2 b2 c2 d2
3 a3 b3 c3 d3
0 n1 n2 n3 n4
A, B, C, D라는 열 이름을 가지며 하나의 행으로 이루어진 데이터프레임을 생성하여 연결하였다.
같은 열이름을 가진 데이터프레임을 연결하면 데이터프레임이 행 방향으로 연결된다.
이렇게 연결된 데이터프레임은 부자연스러운 인덱스를 가진다. 이때, ignore_index=True를 사용하면 처음부터 다시 인덱스를 설정힐 수 있다.
data_dict = {'A': 'n1', 'B': 'n2', 'C': 'n3', 'D': 'n4'}
print(df1.append(data_dict, ignore_index=True))
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 n1 n2 n3 n4
이제 앞선 df1, df2, df3를 행 방향으로 연결할 수 있다.
그리고 axis=1로 해주면 데이터가 열 방향으로 연결된다.
row_concat_i = pd.concat([df1, df2, df3], ignore_index=True)
print(row_concat_i)
col_concat = pd.concat([df1, df2, df3], axis=1)
print(col_concat)
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
10 a10 b10 c10 d10
11 a11 b11 c11 d11
A B C D A B C D A B C D
0 a0 b0 c0 d0 a4 b4 c4 d4 a8 b8 c8 d8
1 a1 b1 c1 d1 a5 b5 c5 d5 a9 b9 c9 d9
2 a2 b2 c2 d2 a6 b6 c6 d6 a10 b10 c10 d10
3 a3 b3 c3 d3 a7 b7 c7 d7 a11 b11 c11 d11
col_concat에 ignore_index=True를 해주면 열 이름이 영어이더라도 숫자로 변한다.
0 1 2 3 4 5 6 7 8 9 10 11
0 a0 b0 c0 d0 a4 b4 c4 d4 a8 b8 c8 d8
1 a1 b1 c1 d1 a5 b5 c5 d5 a9 b9 c9 d9
2 a2 b2 c2 d2 a6 b6 c6 d6 a10 b10 c10 d10
3 a3 b3 c3 d3 a7 b7 c7 d7 a11 b11 c11 d11
데이터프레임에 열을 추가하듯이 열 이름을 담은 리스트를 넣어주면 이름이 바뀐다.
df1.columns = ['A', 'B', 'C', 'D'] # 각 데이터의 열 이름을 바꿔줌.
df2.columns = ['E', "F", "G", "H"]
df3.columns = ['A', "C", "F", "H"]
print(df2)
E F G H
0 a4 b4 c4 d4
1 a5 b5 c5 d5
2 a6 b6 c6 d6
3 a7 b7 c7 d7
데이터프레임을 행 방향으로 합칠 때, 공통되지 않는 열 이름의 데이터는 누락값으로 처리된다.
row_concat_2 = pd.concat([df1, df2, df3])
print(row_concat_2)
A B C D E F G H
0 a0 b0 c0 d0 NaN NaN NaN NaN
1 a1 b1 c1 d1 NaN NaN NaN NaN
2 a2 b2 c2 d2 NaN NaN NaN NaN
3 a3 b3 c3 d3 NaN NaN NaN NaN
0 NaN NaN NaN NaN a4 b4 c4 d4
1 NaN NaN NaN NaN a5 b5 c5 d5
2 NaN NaN NaN NaN a6 b6 c6 d6
3 NaN NaN NaN NaN a7 b7 c7 d7
0 a8 NaN b8 NaN NaN c8 NaN d8
1 a9 NaN b9 NaN NaN c9 NaN d9
2 a10 NaN b10 NaN NaN c10 NaN d10
3 a11 NaN b11 NaN NaN c11 NaN d11
pd.concat으로 데이터프레임을 합칠 때 join='inner'로 설정해주면 연결한 데이터프레임간의 공통 열의 데이터들만 합쳐진다.
만약 공통 열이 존재하지 않으면 empty DataFrame이 출력된다.
print(pd.concat([df1, df3], ignore_index=True, join='inner'))
A C
0 a0 c0
1 a1 c1
2 a2 c2
3 a3 c3
4 a8 b8
5 a9 b9
6 a10 b10
7 a11 b11
열 방향으로도 같은 방법으로 데이터를 연결할 수 있다.
똑같은 방법이기 때문에 넘어가도록 하자.
다음으로 merge메서드에 대해 알아보자.
merge메서드는 concat과는 다르게 기본적으로 내부에서 join='inner'가 설정되어 있기 때문에 누락값이 존재하지 않는다.
또한 연결하려는 두 데이터프레임간의 같은 값을 갖는 열이 존재해야 한다는 특징이 있다.
4개의 데이터를 가져와서 데이터를 확인해보자.
A C
0 a0 c0
1 a1 c1
2 a2 c2
3 a3 c3
4 a8 b8
5 a9 b9
6 a10 b10
7 a11 b11
ident personal family
0 dyer William Dyer
1 pb Frank Pabodie
2 lake Anderson Lake
3 roe Valentina Roerich
4 danforth Frank Danforth
name lat long
0 DR-1 -49.85 -128.57
1 DR-3 -47.15 -126.72
2 MSK-4 -48.87 -123.40
ident site dated
0 619 DR-1 1927-02-08
1 622 DR-1 1927-02-10
2 734 DR-3 1939-01-07
3 735 DR-3 1930-01-12
4 751 DR-3 1930-02-26
5 752 DR-3 NaN
6 837 MSK-4 1932-01-14
7 844 DR-1 1932-03-22
taken person quant reading
0 619 dyer rad 9.82
1 619 dyer sal 0.13
2 622 dyer rad 7.80
3 622 dyer sal 0.09
4 734 pb rad 8.41
5 734 lake sal 0.05
6 734 pb temp -21.50
7 735 pb rad 7.22
8 735 NaN sal 0.06
9 735 NaN temp -26.00
10 751 pb rad 4.35
11 751 pb temp -18.50
12 751 lake sal 0.10
13 752 lake rad 2.19
14 752 lake sal 0.09
15 752 lake temp -16.00
16 752 roe sal 41.60
17 837 lake rad 1.46
18 837 lake sal 0.21
19 837 roe sal 22.50
20 844 roe rad 11.25
site가 3행으로 이루어져 있으므로 먼저 visited의 0, 2, 6행만 가져와서 merge 해보자.
merge 메서드를 사용한 데이터프레임(site)를 왼쪽, 첫번째 인잣값(visited_subset)이 오른쪽 데이터프레임으로 연결된다.
leff_on과 right_on인자는 왼쪽과 오른쪽 데이터프레임에서 같은 값을 갖는 열을 지정해줘야 한다. 지정하지 않으면 코드 실행되지 않는다.
이때 left_on은 왼쪽 데이터프레임(site)의 열(name), right_on은 오른쪽 데이터프레임(visited_subset)의 열(site)을 지정하고 이 두 열의 값이 같아야 한다. 다른 값을 가지는 열을 지정하면 에러가 발생하며 concat 메서드를 사용하라고 한다.
visited_subset = visited.loc[[0, 2, 6], ] # 데이터프레임 visited의 일부.
o2o_merge = site.merge(visited_subset, left_on='name', right_on='site')
print(o2o_merge)
name lat long ident site dated
0 DR-1 -49.85 -128.57 619 DR-1 1927-02-08
1 DR-3 -47.15 -126.72 734 DR-3 1939-01-07
2 MSK-4 -48.87 -123.40 837 MSK-4 1932-01-14
name열과 site열의 데이터가 같은 값을 가지는 것을 알 수 있다.
merge는 concat과 마찬가지로 행의 수가 달라도 된다. 하지만 concat과는 다르게 merge를 사용하면 데이터를 합치면서 누락값까지 한 번에 제거해준다는 이점이 있다.
m2o_merge = site.merge(visited, left_on='name', right_on='site')
print(m2o_merge)
name lat long ident site dated
0 DR-1 -49.85 -128.57 619 DR-1 1927-02-08
1 DR-1 -49.85 -128.57 622 DR-1 1927-02-10
2 DR-1 -49.85 -128.57 844 DR-1 1932-03-22
3 DR-3 -47.15 -126.72 734 DR-3 1939-01-07
4 DR-3 -47.15 -126.72 735 DR-3 1930-01-12
5 DR-3 -47.15 -126.72 751 DR-3 1930-02-26
6 DR-3 -47.15 -126.72 752 DR-3 NaN
7 MSK-4 -48.87 -123.40 837 MSK-4 1932-01-14
dated의 NaN은 원래 visited에 존재하는 누락값이다. merge 메서드가 합칠 때 생기는 누락값은 제거하지만 기존에 데이터가 가지고 있던 누락값은 제거하지 못한다.
person과 survey, visited와 survey도 merge해보자.
ps = person.merge(survey, left_on='ident', right_on='person')
print(ps)
ident personal family taken person quant reading
0 dyer William Dyer 619 dyer rad 9.82
1 dyer William Dyer 619 dyer sal 0.13
2 dyer William Dyer 622 dyer rad 7.80
3 dyer William Dyer 622 dyer sal 0.09
4 pb Frank Pabodie 734 pb rad 8.41
5 pb Frank Pabodie 734 pb temp -21.50
6 pb Frank Pabodie 735 pb rad 7.22
7 pb Frank Pabodie 751 pb rad 4.35
8 pb Frank Pabodie 751 pb temp -18.50
9 lake Anderson Lake 734 lake sal 0.05
10 lake Anderson Lake 751 lake sal 0.10
11 lake Anderson Lake 752 lake rad 2.19
12 lake Anderson Lake 752 lake sal 0.09
13 lake Anderson Lake 752 lake temp -16.00
14 lake Anderson Lake 837 lake rad 1.46
15 lake Anderson Lake 837 lake sal 0.21
16 roe Valentina Roerich 752 roe sal 41.60
17 roe Valentina Roerich 837 roe sal 22.50
18 roe Valentina Roerich 844 roe rad 11.25
열 person의 dyer, pb, lake, roe를 기준으로 하여 순서대로 같은 값을 갖는 데이터를 정렬하며 연결한 것을 확인할 수 있다.
데이터프레임 person의 danforth는 survey에는 존재하지 않는 값이므로 join이 적용되어 결과에 포함되지 않는다.
vs = visited.merge(survey, left_on='ident', right_on='taken')
print(vs)
ident site dated taken person quant reading
0 619 DR-1 1927-02-08 619 dyer rad 9.82
1 619 DR-1 1927-02-08 619 dyer sal 0.13
2 622 DR-1 1927-02-10 622 dyer rad 7.80
3 622 DR-1 1927-02-10 622 dyer sal 0.09
4 734 DR-3 1939-01-07 734 pb rad 8.41
5 734 DR-3 1939-01-07 734 lake sal 0.05
6 734 DR-3 1939-01-07 734 pb temp -21.50
7 735 DR-3 1930-01-12 735 pb rad 7.22
8 735 DR-3 1930-01-12 735 NaN sal 0.06
9 735 DR-3 1930-01-12 735 NaN temp -26.00
10 751 DR-3 1930-02-26 751 pb rad 4.35
11 751 DR-3 1930-02-26 751 pb temp -18.50
12 751 DR-3 1930-02-26 751 lake sal 0.10
13 752 DR-3 NaN 752 lake rad 2.19
14 752 DR-3 NaN 752 lake sal 0.09
15 752 DR-3 NaN 752 lake temp -16.00
16 752 DR-3 NaN 752 roe sal 41.60
17 837 MSK-4 1932-01-14 837 lake rad 1.46
18 837 MSK-4 1932-01-14 837 lake sal 0.21
19 837 MSK-4 1932-01-14 837 roe sal 22.50
20 844 DR-1 1932-03-22 844 roe rad 11.25
마지막으로 ps와 vs를 merge해보자.
두 데이터프레임은 서로 공통되는 열이 많아 리스트 형태로 모두 넘겨주어야 한다.
ps와 vs의 중복된 열 이름은 접미사 _x 또는 _y가 추가되는 것을 확인할 수 있다. _x는 왼쪽 데이터프레임, _y는 오른쪽 데이터프레임의 열 이름에 추가된다.
ps_vs = ps.merge(vs, left_on=['ident', 'taken', 'quant', 'reading'],
right_on=['person', 'ident', 'quant', 'reading'])
print(ps_vs.head())
ident_x personal family taken_x person_x quant reading ident_y site \
0 dyer William Dyer 619 dyer rad 9.82 619 DR-1
1 dyer William Dyer 619 dyer sal 0.13 619 DR-1
2 dyer William Dyer 622 dyer rad 7.80 622 DR-1
3 dyer William Dyer 622 dyer sal 0.09 622 DR-1
4 pb Frank Pabodie 734 pb rad 8.41 734 DR-3
dated taken_y person_y
0 1927-02-08 619 dyer
1 1927-02-08 619 dyer
2 1927-02-10 622 dyer
3 1927-02-10 622 dyer
4 1939-01-07 734 pb
'Pandas' 카테고리의 다른 글
[Do it! Pandas] 7. 깔끔한 데이터 (0) | 2023.02.12 |
---|---|
[Do it! Pandas] 6. 누락값 처리하기 (0) | 2023.02.12 |
[Do it! Pandas] 4. matplotlib 라이브러리를 이용한 다양한 그래프 그리기 (0) | 2023.02.10 |
[Do it! Pandas] 데이터프레임과 시리즈, 브로드캐스팅 (0) | 2023.02.09 |
[Do it! Pandas] 데이터프레임과 시리즈, 간단한 그래프 그리기 (0) | 2023.02.08 |