공지

이번에 준비한 튜토리얼은 제 강의를 듣는 과거-현재-미래 수강생분들을 위해 준비한 자료이다. 많은 도움이 되기를 바란다

이번에 준비한 Tutorial 코로나 세계현황을 Shiny Dashboard로 만들어 가는 과정을 담았다.

I. Shiny Tutorial 소개

처음 shiny를 접하거나 shiny의 전체 튜토리얼이 궁금한 사람들을 위해 이전 글을 소개한다.

II. Shiny Project

현재 진행중인 프로젝트가 궁금하다면 아래를 확인해보자.

III. 생각해볼 문제

생각해볼 문제, sliderInput의 기능을 활용한다는 것의 의미는 매일매일 데이터가 변화하는 것을 확인하는 것에 의미가 있다. 누적데이터가 중요한지, 아니면 매일매일 업데이트된 데이터가 중요한지에 따라 대시보드의 성격이 달라진다.

우선, 누적데이터는 line Graph를 통해서 한번 보여줬기 때문에, 여기에서는 생략하겠다.

날짜가 변화할 때마다 국가별 Case가 달라지는 과정을 보여주고자 한다. 그런데, 문제가 있다.

IV. 데이터 처리의 문제점

이 튜토리얼을 계속 따라왔다면, 다양한 데이터셋이 사용되고 있음을 알 수 있다. - corona 데이터셋 - 지도 데이터셋

지도 데이터셋은 sp라는 특별한 객체로 이루어져 있고, 이미 깔끔하게 국가별 지도 mapping까지 완료된 데이터셋이다.

그럼 여기에서 기준이 데이터셋이 무엇일까? 당연히 지도 데이터셋이다. 강사가 시간을 가장 많이 허비한 포인트가 이 지점이다. 이 글을 읽는 사람은 그러려니 하겠지만, 사실 매우 중요하다. 왜냐하면, 지도가 Plotting 되지 않는다!

(1) 지도 데이터셋에 포함된 국가의 숫자

우선 지도 데이터셋을 좀 더 면밀히 확인해보자.

library(rgdal)
## Loading required package: sp
## rgdal: version: 1.4-8, (SVN revision 845)
##  Geospatial Data Abstraction Library extensions to R successfully loaded
##  Loaded GDAL runtime: GDAL 2.4.2, released 2019/06/28
##  Path to GDAL shared files: /Library/Frameworks/R.framework/Versions/3.6/Resources/library/rgdal/gdal
##  GDAL binary built with GEOS: FALSE 
##  Loaded PROJ.4 runtime: Rel. 5.2.0, September 15th, 2018, [PJ_VERSION: 520]
##  Path to PROJ.4 shared files: /Library/Frameworks/R.framework/Versions/3.6/Resources/library/rgdal/proj
##  Linking to sp version: 1.3-2
countries <- readOGR(dsn ="~/Desktop/ne_50m_admin_0_countries",
                     layer = "ne_50m_admin_0_countries",
                     encoding = "utf-8",use_iconv = T,
                     verbose = FALSE)

length(unique(countries$NAME))
## [1] 241

우선 241개로 확인이 된다.

(2) corona 데이터셋 국가의 숫자

이번에는 다운로드 엑셀 파일을 Import 하여 실제 국가의 숫자가 몇개인지 확인해본다.

library(readxl)
library(httr)

# URL Copy
url <- 'https://www.ecdc.europa.eu/sites/default/files/documents/COVID-19-geographic-disbtribution-worldwide.xlsx'

# 파일 이름만 가져오기
getFileName <- basename(url)

# 지정된 디렉토리에 파일 다운로드 받기
download.file(url = url, destfile = getFileName)

# 지정된 디렉토리에서 파일 업로드 하기
corona <- read_excel(getFileName)
length(unique(corona$countriesAndTerritories))
## [1] 206

일단 countries 데이터셋의 국가의 숫자와 corona 데이터셋의 국가의 숫자가 다른 것이 눈에 띈다.

어떻게 해결 할 것인가? 하는 문제점이 발생한다.

(3) 동일 국가이나 기재된 값이 상호 다른 경우

우선 U로 시작하는 국가를 양쪽에서 추출한 후 비교해보자.

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(stringr)
country_names <- as.character(countries$NAME)
corona_names <- as.character(unique(corona$countriesAndTerritories))

print(data.frame(
  from_countries = c(country_names[str_detect(country_names, pattern = "^U") == TRUE], "empty"), 
  from_corona = corona_names[str_detect(corona_names, pattern = "^U") == TRUE]
))
##             from_countries                  from_corona
## 1               Uzbekistan                       Uganda
## 2                  Uruguay                      Ukraine
## 3          U.S. Virgin Is.         United_Arab_Emirates
## 4 United States of America               United_Kingdom
## 5           United Kingdom  United_Republic_of_Tanzania
## 6     United Arab Emirates     United_States_of_America
## 7                  Ukraine United_States_Virgin_Islands
## 8                   Uganda                      Uruguay
## 9                    empty                   Uzbekistan

위 데이터에서 볼 수 있는 것처럼, 똑같은 미국이지만, 표기법이 다르다. (강사의 혼잣말, 고치는 방법이 있기는 하다. 그런데, 쉽지가 않다! 강의의 본질은 고생은 수강생이 하는게 아니라 원래 강의 준비하는 사람이 하는거다!)

우선 진행방법은 아래와 같다. 여기에서 국가명을 고쳐야 하는 건, corona 데이터셋이다.

수정하는 방법은 아래와 같다.

library(dplyr)
library(stringr)

corona$countriesAndTerritories[corona$countriesAndTerritories =="United_Arab_Emirates"]<- "United Arab Emirates"
corona$countriesAndTerritories[corona$countriesAndTerritories =="United_States_Virgin_Islands"]<- "U.S. Virgin Is."
corona$countriesAndTerritories[corona$countriesAndTerritories =="United_States_of_America"]<- "United States of America"
corona$countriesAndTerritories[corona$countriesAndTerritories =="United_Republic_of_Tanzania"]<- "empty"

country_names <- sort(as.character(countries$NAME), decreasing = TRUE)
corona_names <- sort(as.character(unique(corona$countriesAndTerritories)), decreasing = TRUE)

print(data.frame(
  from_countries = c(country_names[str_detect(country_names, pattern = "^U") == TRUE]), 
  from_corona = corona_names[str_detect(corona_names, pattern = "^U") == TRUE]
))
##             from_countries              from_corona
## 1               Uzbekistan               Uzbekistan
## 2                  Uruguay                  Uruguay
## 3 United States of America           United_Kingdom
## 4           United Kingdom United States of America
## 5     United Arab Emirates     United Arab Emirates
## 6                  Ukraine                  Ukraine
## 7                   Uganda                   Uganda
## 8          U.S. Virgin Is.          U.S. Virgin Is.

위와 같은 방식으로 일일이 수정해야 한다! 갑자기 머리가 아파온다. 원래 데이터싸이언티스트는 80%의 잡무20%의 우아함으로 이루어진다고 한다. 이런일을 즐거워 해야 한다. 걱정마시라, 이미 데이터 전처리 된 데이터는 별도로 URL을 알려줄 것이다.

(4) corona 데이터 가공하기

여전히 한가지 더 큰 어려움이 있다. 241개의 데이터셋을 맞춰야 한다. 그런데, countries@data의 행은 241개이지만, corona의 행은 206개이다. 어떻게 맞춰야 할까?

우선, corona데이터를 넓게 할 필요가 있다. 이유는 국가가 기준이기 때문이다. 즉, 국가가 첫번째 열에 오면 더 좋다.

이 때, 우리에게 필요한 지식은 tidyr 패키지의 gather & spread 함수의 사용법이다. 자세한 설명이 필요하면 tidyr에서 확인해보자.

library(dplyr)
library(tidyr)

corona %>% 
  select(dateRep, countriesAndTerritories, cases) %>% # 필요한 열만 추출한다. 
  group_by_at(vars(-cases)) %>% # cases를 제외하고 모두 그룹을 한다는 뜻이다. 
  dplyr::mutate(row_id=1:n()) %>% ungroup() %>%  # 그룹 인덱스를 만든다.
  spread(key=dateRep, value=cases) %>% # 
  select(-row_id) -> dataCases # 인덱스 제거 후 corona2로 저장한다. 

glimpse(dataCases)
## Rows: 206
## Columns: 107
## $ countriesAndTerritories <chr> "Afghanistan", "Albania", "Algeria", "Andorra…
## $ `2019-12-31`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-01`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-02`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-03`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-04`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-05`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-06`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-07`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-08`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-09`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-10`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-11`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-12`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-13`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-14`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-15`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-16`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-17`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-18`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-19`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-20`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-21`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-22`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-23`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-24`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-25`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 1, 0, 0,…
## $ `2020-01-26`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 3, 0, 0,…
## $ `2020-01-27`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-28`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-29`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-01-30`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 2, 0, 0,…
## $ `2020-01-31`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 1, 0, 0,…
## $ `2020-02-01`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 2, 0, 0,…
## $ `2020-02-02`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 2, 0, 0,…
## $ `2020-02-03`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-02-04`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-02-05`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 1, 0, 0,…
## $ `2020-02-06`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 1, 0, 0,…
## $ `2020-02-07`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 1, 0, 0,…
## $ `2020-02-08`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-02-09`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-02-10`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-02-11`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-02-12`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-02-13`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-02-14`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 1, 0, 0,…
## $ `2020-02-15`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-02-16`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-02-17`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-02-18`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-02-19`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-02-20`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-02-21`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 2, 0, 0,…
## $ `2020-02-22`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 4, 0, 0,…
## $ `2020-02-23`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 1, 0, 0,…
## $ `2020-02-24`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-02-25`            <dbl> 1, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 0, 0,…
## $ `2020-02-26`            <dbl> 0, NA, 1, NA, NA, NA, NA, NA, 0, NA, 0, 2, 0,…
## $ `2020-02-27`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 1, 0, 0,…
## $ `2020-02-28`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 0, 3, 0,…
## $ `2020-02-29`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 0, NA, 2, 2, 1,…
## $ `2020-03-01`            <dbl> 0, NA, 0, NA, NA, NA, NA, NA, 1, NA, 1, 3, 0,…
## $ `2020-03-02`            <dbl> 0, NA, 2, NA, NA, NA, NA, NA, 0, NA, 3, 4, 2,…
## $ `2020-03-03`            <dbl> NA, NA, NA, 1, NA, NA, NA, NA, NA, NA, 4, 4, …
## $ `2020-03-04`            <dbl> NA, NA, 2, NA, NA, NA, NA, 1, NA, NA, 8, 6, N…
## $ `2020-03-05`            <dbl> NA, NA, 7, NA, NA, NA, NA, NA, NA, NA, 11, 5,…
## $ `2020-03-06`            <dbl> NA, NA, 5, NA, NA, NA, NA, 1, NA, NA, 7, 12, …
## $ `2020-03-07`            <dbl> NA, NA, NA, NA, NA, NA, NA, 6, NA, NA, 4, 33,…
## $ `2020-03-08`            <dbl> 3, NA, NA, NA, NA, NA, NA, 1, NA, NA, 11, 25,…
## $ `2020-03-09`            <dbl> NA, 2, 3, NA, NA, NA, NA, 3, NA, NA, 6, 3, NA…
## $ `2020-03-10`            <dbl> NA, 4, NA, NA, NA, NA, NA, NA, NA, NA, 20, 29…
## $ `2020-03-11`            <dbl> 3, 4, NA, NA, NA, NA, NA, 7, NA, NA, 12, 51, …
## $ `2020-03-12`            <dbl> NA, 1, 0, NA, NA, NA, NA, NA, 3, NA, 14, 64, …
## $ `2020-03-13`            <dbl> NA, 12, 4, NA, NA, NA, NA, 12, 2, 2, 30, 115,…
## $ `2020-03-14`            <dbl> NA, 10, 2, 1, NA, NA, NA, 3, 7, NA, 41, 143, …
## $ `2020-03-15`            <dbl> 3, 5, 11, NA, NA, NA, 1, 11, 7, NA, 52, 151, …
## $ `2020-03-16`            <dbl> 6, 4, 11, 3, NA, NA, NA, 11, 10, NA, 49, 205,…
## $ `2020-03-17`            <dbl> 5, 9, 12, 9, NA, NA, NA, 9, 22, NA, 77, 156, …
## $ `2020-03-18`            <dbl> 1, 4, 0, 0, NA, NA, NA, 14, 26, NA, 79, 316, …
## $ `2020-03-19`            <dbl> 0, 4, 13, 39, NA, NA, NA, 18, 37, NA, 111, 31…
## $ `2020-03-20`            <dbl> 0, 11, 9, 22, NA, NA, NA, 31, 7, 2, 144, 550,…
## $ `2020-03-21`            <dbl> 2, 0, 12, 0, NA, NA, 0, 30, 14, NA, 165, 453,…
## $ `2020-03-22`            <dbl> 0, 6, 0, 13, 2, NA, 0, 67, 24, NA, 224, 375, …
## $ `2020-03-23`            <dbl> 10, 13, 8, 25, 0, NA, 0, 41, 30, NA, 611, 607…
## $ `2020-03-24`            <dbl> 6, 11, 87, 20, 0, NA, 0, 35, 4, 8, 114, 855, …
## $ `2020-03-25`            <dbl> 2, 23, 42, 31, 0, NA, 2, 86, 71, 5, 600, 796,…
## $ `2020-03-26`            <dbl> 33, 23, 33, 24, 0, NA, 0, 115, 25, 2, 376, 60…
## $ `2020-03-27`            <dbl> 0, 28, 41, 36, 1, 2, 4, 87, 39, 9, 367, 1141,…
## $ `2020-03-28`            <dbl> 16, 12, 0, 43, 1, 0, 0, 101, 43, 0, 212, 668,…
## $ `2020-03-29`            <dbl> 15, 11, 104, 41, 0, 0, 0, 55, 52, 0, 431, 594…
## $ `2020-03-30`            <dbl> 8, 15, 45, 26, 3, 0, 0, 75, 0, 22, 284, 522, …
## $ `2020-03-31`            <dbl> 27, 11, 57, 36, 0, 0, 0, 146, 58, NA, 464, 80…
## $ `2020-04-01`            <dbl> 25, 20, 73, 6, 0, 0, 0, 0, 50, 5, 150, 564, 2…
## $ `2020-04-02`            <dbl> 26, 16, 263, 14, 1, 0, 0, 167, 39, 0, 269, 52…
## $ `2020-04-03`            <dbl> 43, 18, 0, 38, 0, 1, 2, 0, 92, 5, 248, 418, 4…
## $ `2020-04-04`            <dbl> 0, 27, 139, 11, 0, 0, 6, 132, 73, 2, 324, 396…
## $ `2020-04-05`            <dbl> 35, 29, 314, 27, 2, 0, 0, 186, 34, 2, 139, 24…
## $ `2020-04-06`            <dbl> 29, 28, 20, 35, 4, 0, 0, 103, 52, 0, 57, 217,…
## $ `2020-04-07`            <dbl> 38, 16, 103, 25, 2, 0, 0, 74, 11, 7, 100, 314…
## $ `2020-04-08`            <dbl> 30, 6, 45, 19, 1, 0, 0, 87, 20, 3, 112, 343, …
## $ `2020-04-09`            <dbl> 56, 17, 104, 19, 2, 0, 0, 80, 28, 3, 96, 329,…
## $ `2020-04-10`            <dbl> 61, 9, 94, 19, 0, 0, 4, 99, 40, 5, 100, 279, …
## $ `2020-04-11`            <dbl> 37, 7, 95, 18, 0, 0, 2, 81, 16, 4, 86, 312, 6…
## $ `2020-04-12`            <dbl> 34, 17, 64, 21, 0, 0, 0, 162, 30, 6, 51, 247,…
## $ `2020-04-13`            <dbl> 52, 13, 89, 16, 0, 0, 0, 66, 46, 0, 33, 130, …
## $ `2020-04-14`            <dbl> 58, 21, 69, 8, 0, 0, 2, 69, 26, 0, 44, 106, 5…

(5) 241개의 행으로 맞추기

이제 Table Join을 활용해야 한다. 이 때 조인키를 확인해야 한다. 그리고 countries 데이터셋에 맞추도록 한다.

coronaConfirmed <- left_join(data.frame(countries = countries$NAME %>% as.character(), 
                                   Pop = countries$POP_EST %>% as.character() %>% as.numeric()), 
                        dataCases %>% 
  rename(countries = countriesAndTerritories)) %>% 
  filter(!is.na(countries))
## Joining, by = "countries"
## Warning: Column `countries` joining factor and character vector, coercing into
## character vector
glimpse(coronaConfirmed)
## Rows: 241
## Columns: 108
## $ countries    <chr> "Zimbabwe", "Zambia", "Yemen", "Vietnam", "Venezuela", "…
## $ Pop          <dbl> 13805084, 15972000, 28036829, 96160163, 31304016, 1000, …
## $ `2019-12-31` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-01` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-02` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-03` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-04` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-05` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-06` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-07` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-08` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-09` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-10` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-11` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-12` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-13` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-14` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-15` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-16` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-17` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-18` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-19` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-20` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-21` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-22` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-23` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-24` <dbl> NA, NA, NA, 2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-25` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-26` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-27` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-28` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-29` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-30` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-01-31` <dbl> NA, NA, NA, 3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-01` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-02` <dbl> NA, NA, NA, 2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-03` <dbl> NA, NA, NA, 1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-04` <dbl> NA, NA, NA, 1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-05` <dbl> NA, NA, NA, 1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-06` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-07` <dbl> NA, NA, NA, 2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-08` <dbl> NA, NA, NA, 1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-09` <dbl> NA, NA, NA, 1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-10` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-11` <dbl> NA, NA, NA, 1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-12` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-13` <dbl> NA, NA, NA, 1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-14` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-15` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-16` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-17` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-18` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-19` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-20` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-21` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-22` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-23` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-24` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-25` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-26` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-27` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-28` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-02-29` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-03-01` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-03-02` <dbl> NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-03-03` <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ `2020-03-04` <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ `2020-03-05` <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ `2020-03-06` <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ `2020-03-07` <dbl> NA, NA, NA, 1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-03-08` <dbl> NA, NA, NA, 4, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-03-09` <dbl> NA, NA, NA, 9, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-03-10` <dbl> NA, NA, NA, 1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-03-11` <dbl> NA, NA, NA, 4, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-03-12` <dbl> NA, NA, NA, 4, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-03-13` <dbl> NA, NA, NA, 5, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-03-14` <dbl> NA, NA, NA, 5, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `2020-03-15` <dbl> NA, NA, NA, 4, 10, NA, NA, NA, 6, NA, NA, NA, NA, NA, NA…
## $ `2020-03-16` <dbl> NA, NA, NA, 4, 5, NA, NA, 6, 2, NA, NA, NA, NA, NA, NA, …
## $ `2020-03-17` <dbl> NA, NA, NA, 4, 18, NA, NA, 2, 21, NA, NA, NA, NA, NA, NA…
## $ `2020-03-18` <dbl> NA, NA, NA, 0, 0, NA, NA, 8, 21, NA, NA, NA, NA, NA, NA,…
## $ `2020-03-19` <dbl> NA, 2, NA, 15, 0, NA, NA, 7, 29, NA, NA, NA, NA, 3, NA, …
## $ `2020-03-20` <dbl> NA, 0, NA, 9, 0, NA, NA, 0, 15, NA, NA, NA, NA, 9, NA, N…
## $ `2020-03-21` <dbl> 1, 0, NA, 2, 3, NA, NA, 10, 16, NA, NA, NA, NA, 2, NA, N…
## $ `2020-03-22` <dbl> 1, 0, NA, 7, 0, NA, NA, 0, 25, NA, NA, NA, NA, 1, NA, NA…
## $ `2020-03-23` <dbl> 0, 1, NA, 24, 0, NA, NA, 13, 23, NA, NA, NA, NA, 12, NA,…
## $ `2020-03-24` <dbl> 0, 0, NA, 5, 48, NA, NA, 3, 4, NA, NA, NA, 17, 2, NA, NA…
## $ `2020-03-25` <dbl> 0, 0, NA, 11, 7, NA, NA, 6, 27, NA, NA, NA, 0, 3, NA, NA…
## $ `2020-03-26` <dbl> 1, 9, NA, 14, 15, NA, NA, 10, 28, NA, NA, NA, 0, 5, NA, …
## $ `2020-03-27` <dbl> 0, 2, NA, 5, 1, NA, NA, 18, 21, NA, NA, NA, 0, 12, NA, N…
## $ `2020-03-28` <dbl> 2, 2, NA, 16, 12, NA, NA, 21, 0, NA, NA, NA, 2, 2, NA, N…
## $ `2020-03-29` <dbl> 2, 12, NA, 54, 0, NA, NA, 29, 66, NA, NA, NA, 3, 4, NA, …
## $ `2020-03-30` <dbl> 0, 1, NA, 5, 0, NA, NA, 12, 5, NA, NA, NA, 8, 1, NA, NA,…
## $ `2020-03-31` <dbl> 0, 6, NA, 1, 16, NA, NA, 4, 11, NA, NA, NA, NA, 4, NA, N…
## $ `2020-04-01` <dbl> 1, 0, NA, 0, 0, NA, NA, 24, 18, NA, NA, NA, 0, 9, NA, NA…
## $ `2020-04-02` <dbl> 0, 1, NA, 6, 8, NA, NA, 14, 0, NA, NA, NA, 0, 8, NA, NA,…
## $ `2020-04-03` <dbl> 0, 3, NA, 4, 1, NA, NA, 3, 31, NA, NA, NA, 3, 5, NA, NA,…
## $ `2020-04-04` <dbl> 1, 0, NA, 0, 0, NA, NA, 37, 17, NA, NA, NA, 7, 5, NA, NA…
## $ `2020-04-05` <dbl> 0, 0, NA, 1, 0, NA, NA, 39, 14, NA, NA, NA, 0, 6, NA, NA…
## $ `2020-04-06` <dbl> 0, 0, NA, 1, 4, NA, NA, 76, 6, NA, NA, NA, 2, 17, NA, NA…
## $ `2020-04-07` <dbl> 0, 0, NA, 4, 11, NA, NA, 55, 9, NA, NA, NA, 0, 2, NA, NA…
## $ `2020-04-08` <dbl> 1, 0, NA, 6, 7, NA, NA, 107, 9, NA, NA, NA, 3, 9, NA, NA…
## $ `2020-04-09` <dbl> 1, 0, NA, 0, 1, NA, NA, 51, 32, NA, NA, NA, 0, 4, NA, NA…
## $ `2020-04-10` <dbl> 0, 0, 1, 4, 4, NA, NA, 27, 17, NA, NA, NA, 5, 3, NA, NA,…
## $ `2020-04-11` <dbl> 0, 1, 0, 2, 4, NA, NA, 42, 21, NA, NA, NA, 0, 2, NA, NA,…
## $ `2020-04-12` <dbl> 3, 0, 0, 1, 0, NA, NA, 172, 7, NA, NA, NA, 1, 3, NA, NA,…
## $ `2020-04-13` <dbl> 0, 3, 0, 4, 6, NA, NA, 69, 11, NA, NA, NA, 0, 0, NA, NA,…
## $ `2020-04-14` <dbl> 3, 2, 0, 3, 8, NA, NA, 133, 9, NA, NA, NA, 0, 1, NA, NA,…

(6) NA값 처리하기

국가 및 날짜별로 case가 정리된 것을 확인할 수 있다. 아직 문제는 끝나지 않았다. 왜냐하면 NA가 있기 때문이다. NA가 포함된 부분은 모두 0으로 처리하자. 왜냐하면, 우리는 숫자로 표시해야 하기 때문에 NA의 공백은 있을 수 없다.

library(ggplot2)

sapply(coronaConfirmed[-c(1:2)],function(x) sum(is.na(x))) %>% as_tibble() %>% 
  mutate(date = as.Date(colnames(coronaConfirmed)[-c(1:2)])) %>% 
  ggplot(aes(x = date, y = value)) + 
    geom_line(size = 1.5, color = "darkblue") + 
    theme_minimal()

NA값 처리에 관한 그래프를 작성한 것이다. 거의 모든 국가에서 발현되기 시작한 3월 이후부터는 NA가 줄어드는 것을 확인할 수 있다. (아! 시각화 분석이 아니다! 빨리 돌아가서 NA를 처리하자)

coronaConfirmed[is.na(coronaConfirmed)] <- 0
sapply(coronaConfirmed[-c(1:2)],function(x) sum(is.na(x))) %>% as_tibble() %>% 
  mutate(date = as.Date(colnames(coronaConfirmed)[-c(1:2)])) %>% 
  ggplot(aes(x = date, y = value)) + 
    geom_line(size = 1.5, color = "darkblue") + 
    theme_minimal()

모든 NA가 0으로 수렴되는 것을 볼 수 있다.

(7) 데이터 저장

이렇게 전처리된 데이터를 다시 사용하기 위해, csv, Database 등 다양한 형태로 저장을 해본다. 이 부분은 수강생의 자율에 맡기도록 한다.

V. 수강생을 위한 과제

지금까지 한것은 확진자(casesConfirmed) 데이터를 가지고 전처리를 진행하였다. 그러나, 확진후 사망자 수 데이터도 중요하며, 더 나아가 인구대비 확진자, 사망자 등도 중요한 데이터가 될 수 있다.

문제는 아직 사망자 수 데이터를 기반으로 작업은 하지 못했다는 점이다. 이 부분은 수강생을 위한 과제로 남겨두겠다.

VI. 결론

이번에는 데이터 전처리에 대해 배우는 시간을 가졌다. 이렇게 데이터 전처리는 어렵다. 강사 역시, 글을 쓰면서 하루의 시간을 모두 통으로 보내며 전처리의 과정을 진행했다. 단순히 소스코드를 짜는 것 뿐만 아니라, 하나씩 확인하는 과정, 좀 더 나은 방법들을 고민하면서 소스코드를 짜는데 주력하였다.

이제 마지막 Chart Automation만 남았다.

이글을 읽는 사람들에게 작게나마 도움이 되기를 바란다.

Pray for Victims of Covid_19. Contribution to them with this tutorial.