8 분 소요


데이터 연결하기

분석하기 좋은 데이터

데이터 분석 작업의 70% 이상을 차지하고 있는 작업이 데이터 정리 작업(데이터 클렌징 작업)

  • 깔끔한 데이터의 조건
    1. 데이터 분석 목적에 맞는 데이터를 모아 새로운 표(table)를 만들어야 한다.
    2. 측정한 값은 행(row)을 구성해야 한다.
    3. 변수는 열(column)로 구성해야 한다.

데이터 연결 기초

  • 데이터 연결하기
In [1]:
import pandas as pd
In [3]:
df1 = pd.read_csv('data/concat_1.csv')
df2 = pd.read_csv('data/concat_2.csv')
df3 = pd.read_csv('data/concat_3.csv')
In [4]:
df1
Out [4]:
A B C D
0 a0 b0 c0 d0
1 a1 b1 c1 d1
2 a2 b2 c2 d2
3 a3 b3 c3 d3
In [5]:
df2
Out [5]:
A B C D
0 a4 b4 c4 d4
1 a5 b5 c5 d5
2 a6 b6 c6 d6
3 a7 b7 c7 d7
In [6]:
df3
Out [6]:
A B C D
0 a8 b8 c8 d8
1 a9 b9 c9 d9
2 a10 b10 c10 d10
3 a11 b11 c11 d11
In [8]:
# 연결하기
pd.concat([df1, df2, df3]) # axis=0(default) # column이 같은것 끼리 연결
Out [8]:
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
In [9]:
pd.concat([df1, df2, df3], axis=1) # idx가 같은것 끼리 연결
Out [9]:
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
In [11]:
# 시리즈 연결하기
new = pd.Series(['n1', 'n2', 'n3', 'n4'])
In [12]:
pd.concat([df1, new]) # outer이기에 매칭되지 않는 값은 NaN으로 출력
Out [12]:
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
In [19]:
# 데이터프레임 연결하기
new_df = pd.DataFrame([['n1', 'n2', 'n3', 'n4']], columns=['A', 'B', 'C', 'D'])
In [20]:
pd.concat([df1, new_df]) # 기본적으로 idx, column이 같은 값 끼리 연결한다.
Out [20]:
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
In [21]:
df1.append(new_df) # 곧 deprecate 됨.. 
Out [21]:
C:\Users\user\AppData\Local\Temp\ipykernel_2208\1709610274.py:1: FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead.
  df1.append(new_df) #

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
In [23]:
pd.concat([df1, df2, df3])
Out [23]:
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
In [22]:
pd.concat([df1, df2, df3], ignore_index=True) # 기존 idx번호를 무시하고 새로부여
Out [22]:
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
In [24]:
pd.concat([df1, new], join='inner') # inner로 할 경우 공통부분이 있는 경우만 출력
Out [24]:
0
1
2
3
0
1
2
3

데이터 연결 마무리

  • merge사용
In [25]:
person = pd.read_csv('data/survey_person.csv')
site = pd.read_csv('data/survey_site.csv')
survey = pd.read_csv('data/survey_survey.csv')
visited = pd.read_csv('data/survey_visited.csv')
In [26]:
visited
Out [26]:
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
In [27]:
sub_visited = visited.loc[[0, 2, 6]]
sub_visited
Out [27]:
ident site dated
0 619 DR-1 1927-02-08
2 734 DR-3 1939-01-07
6 837 MSK-4 1932-01-14
In [None]:
site
Out [None]:
name lat long
0 DR-1 -49.85 -128.57
1 DR-3 -47.15 -126.72
2 MSK-4 -48.87 -123.40

sub_visited의 site column의 값과 site의 name값이 매칭됨

In [30]:
# pd의 merge에는 left, right가 필요 # df의 merge에는 left만 필요(df가 right가 됨)
site.merge(sub_visited, left_on='name', right_on='site') # how옵션의 default는 inner ('left', 'right', 'outer', 'inner', 'cross')
# 기본적으로 column이름이 같으면 on에 한번만 적으면 된다. # 이름이 다를 경우 left_on과 right_on에 각각 적어준다.
Out [30]:
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

concat은 idx나 column이 같을 경우 merge는 데이터 값이 같을 경우(SQL의 join과 유사)

누락값 처리하기

누락값이란?

In [31]:
from numpy import NaN, NAN, nan
In [32]:
NaN == True
Out [32]:
False
In [33]:
nan == True
Out [33]:
False
In [34]:
NAN == False
Out [34]:
False
In [35]:
nan == ''
Out [35]:
False
In [36]:
nan == 0
Out [36]:
False

pd.isnull()
pd.isna()

In [37]:
pd.isna(nan) # pd.notna(nan)
Out [37]:
True
In [39]:
pd.isnull(nan)
Out [39]:
True
In [40]:
pd.notnull(nan)
Out [40]:
False
  • 누락값 갯수 구하기
In [45]:
ebola = pd.read_csv('data/country_timeseries.csv')
ebola.head(3)
Out [45]:
Date Day Cases_Guinea Cases_Liberia Cases_SierraLeone Cases_Nigeria Cases_Senegal Cases_UnitedStates Cases_Spain Cases_Mali Deaths_Guinea Deaths_Liberia Deaths_SierraLeone Deaths_Nigeria Deaths_Senegal Deaths_UnitedStates Deaths_Spain Deaths_Mali
0 1/5/2015 289 2776.0 NaN 10030.0 NaN NaN NaN NaN NaN 1786.0 NaN 2977.0 NaN NaN NaN NaN NaN
1 1/4/2015 288 2775.0 NaN 9780.0 NaN NaN NaN NaN NaN 1781.0 NaN 2943.0 NaN NaN NaN NaN NaN
2 1/3/2015 287 2769.0 8166.0 9722.0 NaN NaN NaN NaN NaN 1767.0 3496.0 2915.0 NaN NaN NaN NaN NaN
In [46]:
ebola.tail(3)
Out [46]:
Date Day Cases_Guinea Cases_Liberia Cases_SierraLeone Cases_Nigeria Cases_Senegal Cases_UnitedStates Cases_Spain Cases_Mali Deaths_Guinea Deaths_Liberia Deaths_SierraLeone Deaths_Nigeria Deaths_Senegal Deaths_UnitedStates Deaths_Spain Deaths_Mali
119 3/25/2014 3 86.0 NaN NaN NaN NaN NaN NaN NaN 60.0 NaN NaN NaN NaN NaN NaN NaN
120 3/24/2014 2 86.0 NaN NaN NaN NaN NaN NaN NaN 59.0 NaN NaN NaN NaN NaN NaN NaN
121 3/22/2014 0 49.0 NaN NaN NaN NaN NaN NaN NaN 29.0 NaN NaN NaN NaN NaN NaN NaN
In [47]:
ebola.count() # 누락값은 제외하고 연산 # 누락값과 연산하면 누락값이 됨
Out [47]:
Date                   122
Day                    122
Cases_Guinea            93
Cases_Liberia           83
Cases_SierraLeone       87
Cases_Nigeria           38
Cases_Senegal           25
Cases_UnitedStates      18
Cases_Spain             16
Cases_Mali              12
Deaths_Guinea           92
Deaths_Liberia          81
Deaths_SierraLeone      87
Deaths_Nigeria          38
Deaths_Senegal          22
Deaths_UnitedStates     18
Deaths_Spain            16
Deaths_Mali             12
dtype: int64
In [50]:
pd.isna(ebola).sum() # isna의 True값만 합한다
Out [50]:
Date                     0
Day                      0
Cases_Guinea            29
Cases_Liberia           39
Cases_SierraLeone       35
Cases_Nigeria           84
Cases_Senegal           97
Cases_UnitedStates     104
Cases_Spain            106
Cases_Mali             110
Deaths_Guinea           30
Deaths_Liberia          41
Deaths_SierraLeone      35
Deaths_Nigeria          84
Deaths_Senegal         100
Deaths_UnitedStates    104
Deaths_Spain           106
Deaths_Mali            110
dtype: int64
In [51]:
pd.isna(ebola).sum().sum() # 전체 누락값
Out [51]:
1214
In [52]:
ebola['Cases_Guinea'].value_counts() # 값 별로 몇번 반복되는지 확인
Out [52]:
86.0      3
495.0     2
112.0     2
390.0     2
408.0     1
         ..
1199.0    1
1298.0    1
1350.0    1
1472.0    1
49.0      1
Name: Cases_Guinea, Length: 88, dtype: int64
  • 누락값 처리(변경, 삭제)
In [54]:
ebola.fillna(0) # 원본은 변경하지 않고 처리된 값을 return함(변경하려면 inplace옵션 사용한거나 df로 받아줘야함)
# 해당 데이터는 누적값이므로 0으로 채우면 안됨
Out [54]:
Date Day Cases_Guinea Cases_Liberia Cases_SierraLeone Cases_Nigeria Cases_Senegal Cases_UnitedStates Cases_Spain Cases_Mali Deaths_Guinea Deaths_Liberia Deaths_SierraLeone Deaths_Nigeria Deaths_Senegal Deaths_UnitedStates Deaths_Spain Deaths_Mali
0 1/5/2015 289 2776.0 0.0 10030.0 0.0 0.0 0.0 0.0 0.0 1786.0 0.0 2977.0 0.0 0.0 0.0 0.0 0.0
1 1/4/2015 288 2775.0 0.0 9780.0 0.0 0.0 0.0 0.0 0.0 1781.0 0.0 2943.0 0.0 0.0 0.0 0.0 0.0
2 1/3/2015 287 2769.0 8166.0 9722.0 0.0 0.0 0.0 0.0 0.0 1767.0 3496.0 2915.0 0.0 0.0 0.0 0.0 0.0
3 1/2/2015 286 0.0 8157.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3496.0 0.0 0.0 0.0 0.0 0.0 0.0
4 12/31/2014 284 2730.0 8115.0 9633.0 0.0 0.0 0.0 0.0 0.0 1739.0 3471.0 2827.0 0.0 0.0 0.0 0.0 0.0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
117 3/27/2014 5 103.0 8.0 6.0 0.0 0.0 0.0 0.0 0.0 66.0 6.0 5.0 0.0 0.0 0.0 0.0 0.0
118 3/26/2014 4 86.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 62.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
119 3/25/2014 3 86.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 60.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
120 3/24/2014 2 86.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 59.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
121 3/22/2014 0 49.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 29.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0

122 rows × 18 columns

In [56]:
ebola.fillna(method='ffill') # 앞의 값으로 채움
Out [56]:
Date Day Cases_Guinea Cases_Liberia Cases_SierraLeone Cases_Nigeria Cases_Senegal Cases_UnitedStates Cases_Spain Cases_Mali Deaths_Guinea Deaths_Liberia Deaths_SierraLeone Deaths_Nigeria Deaths_Senegal Deaths_UnitedStates Deaths_Spain Deaths_Mali
0 1/5/2015 289 2776.0 NaN 10030.0 NaN NaN NaN NaN NaN 1786.0 NaN 2977.0 NaN NaN NaN NaN NaN
1 1/4/2015 288 2775.0 NaN 9780.0 NaN NaN NaN NaN NaN 1781.0 NaN 2943.0 NaN NaN NaN NaN NaN
2 1/3/2015 287 2769.0 8166.0 9722.0 NaN NaN NaN NaN NaN 1767.0 3496.0 2915.0 NaN NaN NaN NaN NaN
3 1/2/2015 286 2769.0 8157.0 9722.0 NaN NaN NaN NaN NaN 1767.0 3496.0 2915.0 NaN NaN NaN NaN NaN
4 12/31/2014 284 2730.0 8115.0 9633.0 NaN NaN NaN NaN NaN 1739.0 3471.0 2827.0 NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
117 3/27/2014 5 103.0 8.0 6.0 0.0 1.0 1.0 1.0 1.0 66.0 6.0 5.0 0.0 0.0 0.0 1.0 1.0
118 3/26/2014 4 86.0 8.0 6.0 0.0 1.0 1.0 1.0 1.0 62.0 6.0 5.0 0.0 0.0 0.0 1.0 1.0
119 3/25/2014 3 86.0 8.0 6.0 0.0 1.0 1.0 1.0 1.0 60.0 6.0 5.0 0.0 0.0 0.0 1.0 1.0
120 3/24/2014 2 86.0 8.0 6.0 0.0 1.0 1.0 1.0 1.0 59.0 6.0 5.0 0.0 0.0 0.0 1.0 1.0
121 3/22/2014 0 49.0 8.0 6.0 0.0 1.0 1.0 1.0 1.0 29.0 6.0 5.0 0.0 0.0 0.0 1.0 1.0

122 rows × 18 columns

In [57]:
ebola.fillna(method='bfill') # 뒤의 값으로 채움
# 해당 데이터는 이 방법으로 채우고 남은 nan은 0으로 채우는게 맞다.
Out [57]:
Date Day Cases_Guinea Cases_Liberia Cases_SierraLeone Cases_Nigeria Cases_Senegal Cases_UnitedStates Cases_Spain Cases_Mali Deaths_Guinea Deaths_Liberia Deaths_SierraLeone Deaths_Nigeria Deaths_Senegal Deaths_UnitedStates Deaths_Spain Deaths_Mali
0 1/5/2015 289 2776.0 8166.0 10030.0 20.0 1.0 4.0 1.0 7.0 1786.0 3496.0 2977.0 8.0 0.0 1.0 0.0 6.0
1 1/4/2015 288 2775.0 8166.0 9780.0 20.0 1.0 4.0 1.0 7.0 1781.0 3496.0 2943.0 8.0 0.0 1.0 0.0 6.0
2 1/3/2015 287 2769.0 8166.0 9722.0 20.0 1.0 4.0 1.0 7.0 1767.0 3496.0 2915.0 8.0 0.0 1.0 0.0 6.0
3 1/2/2015 286 2730.0 8157.0 9633.0 20.0 1.0 4.0 1.0 7.0 1739.0 3496.0 2827.0 8.0 0.0 1.0 0.0 6.0
4 12/31/2014 284 2730.0 8115.0 9633.0 20.0 1.0 4.0 1.0 7.0 1739.0 3471.0 2827.0 8.0 0.0 1.0 0.0 6.0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
117 3/27/2014 5 103.0 8.0 6.0 NaN NaN NaN NaN NaN 66.0 6.0 5.0 NaN NaN NaN NaN NaN
118 3/26/2014 4 86.0 NaN NaN NaN NaN NaN NaN NaN 62.0 NaN NaN NaN NaN NaN NaN NaN
119 3/25/2014 3 86.0 NaN NaN NaN NaN NaN NaN NaN 60.0 NaN NaN NaN NaN NaN NaN NaN
120 3/24/2014 2 86.0 NaN NaN NaN NaN NaN NaN NaN 59.0 NaN NaN NaN NaN NaN NaN NaN
121 3/22/2014 0 49.0 NaN NaN NaN NaN NaN NaN NaN 29.0 NaN NaN NaN NaN NaN NaN NaN

122 rows × 18 columns

In [58]:
ebola.interpolate() # 중간값으로 채움
Out [58]:
Date Day Cases_Guinea Cases_Liberia Cases_SierraLeone Cases_Nigeria Cases_Senegal Cases_UnitedStates Cases_Spain Cases_Mali Deaths_Guinea Deaths_Liberia Deaths_SierraLeone Deaths_Nigeria Deaths_Senegal Deaths_UnitedStates Deaths_Spain Deaths_Mali
0 1/5/2015 289 2776.0 NaN 10030.0 NaN NaN NaN NaN NaN 1786.0 NaN 2977.0 NaN NaN NaN NaN NaN
1 1/4/2015 288 2775.0 NaN 9780.0 NaN NaN NaN NaN NaN 1781.0 NaN 2943.0 NaN NaN NaN NaN NaN
2 1/3/2015 287 2769.0 8166.0 9722.0 NaN NaN NaN NaN NaN 1767.0 3496.0 2915.0 NaN NaN NaN NaN NaN
3 1/2/2015 286 2749.5 8157.0 9677.5 NaN NaN NaN NaN NaN 1753.0 3496.0 2871.0 NaN NaN NaN NaN NaN
4 12/31/2014 284 2730.0 8115.0 9633.0 NaN NaN NaN NaN NaN 1739.0 3471.0 2827.0 NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
117 3/27/2014 5 103.0 8.0 6.0 0.0 1.0 1.0 1.0 1.0 66.0 6.0 5.0 0.0 0.0 0.0 1.0 1.0
118 3/26/2014 4 86.0 8.0 6.0 0.0 1.0 1.0 1.0 1.0 62.0 6.0 5.0 0.0 0.0 0.0 1.0 1.0
119 3/25/2014 3 86.0 8.0 6.0 0.0 1.0 1.0 1.0 1.0 60.0 6.0 5.0 0.0 0.0 0.0 1.0 1.0
120 3/24/2014 2 86.0 8.0 6.0 0.0 1.0 1.0 1.0 1.0 59.0 6.0 5.0 0.0 0.0 0.0 1.0 1.0
121 3/22/2014 0 49.0 8.0 6.0 0.0 1.0 1.0 1.0 1.0 29.0 6.0 5.0 0.0 0.0 0.0 1.0 1.0

122 rows × 18 columns

In [59]:
# nan있는 row 삭제
ebola.dropna()
Out [59]:
Date Day Cases_Guinea Cases_Liberia Cases_SierraLeone Cases_Nigeria Cases_Senegal Cases_UnitedStates Cases_Spain Cases_Mali Deaths_Guinea Deaths_Liberia Deaths_SierraLeone Deaths_Nigeria Deaths_Senegal Deaths_UnitedStates Deaths_Spain Deaths_Mali
19 11/18/2014 241 2047.0 7082.0 6190.0 20.0 1.0 4.0 1.0 6.0 1214.0 2963.0 1267.0 8.0 0.0 1.0 0.0 6.0

Reference

  • 이 포스트는 SeSAC 인공지능 자연어처리, 컴퓨터비전 기술을 활용한 응용 SW 개발자 양성 과정 - 심선조 강사님의 강의를 정리한 내용입니다.

댓글남기기