[R] 코로나 19 자료 및 회귀 모형 (선형, 비선형)을 이용하여 대한민국 사망자 예측 및 가시화

 정보

  • 업무명     : 코로나 19 자료 및 회귀 모형 (선형, 비선형)을 이용하여 대한민국 사망자 예측 및 가시화
  • 작성자     : 이상호
  • 작성일     : 2020-04-07
  • 설   명      :
  • 수정이력 :

 

 내용

[개요]

  • 안녕하세요? 기상 연구 및 웹 개발을 담당하고 있는 해솔입니다.
  • 최근 코로나 19 바이러스가 중국에서 발생하여 전 세계의 일반인들에게 전염되고 있습니다. 신규 코로나 바이러스는 이전에 인간에서 확인된 적이없는 새로운 변종입니다. 이 바이러스와 관련된 위험으로 인해 유엔 세계 보건기구 (WHO)는 세계 보건 비상 사태로 선언했습니다 .
  • 첫 발원지인 우한에서는 2020년 01월 10일에 최초 사망한 이후로 2020년 02월 14일에 1523명으로 급등했습니다. 특히 2020년 02월 14일에 단 하루 만에 143명이 죽었습니다. 전 세계적으로 바이러스는 주요 28개국 이상을 감염시켰습니다.
  • 오늘 포스팅에서는 코로나 19 자료 및 회귀 모형 (선형, 비선형)을 이용하여 대한민국 사망자 예측 및 가시화를 소개해 드리고자 합니다.

 

 

[특징]

  • 코로나 19 자료를 이해하기 위해서 가시화 기술이 요구되며 이 프로그램은 이러한 목적을 달성하기 위한 소프트웨어

 

[기능]

  • 실시간 코로나 19 자료 다운로드
  • 회귀모형을 위한 자료 전처리
  • 누적 사망자수 예측
  • 가시화

 

[활용 자료]

  • 자료 종류 : 코로나 사망자수 자료
  • 확장자 : csv
  • 영역 : 전지구
  • 기간 : 2019년 12월 31일 - 2020년 04월 06일
  • 시간 해상도 : 일 1개
  • 제공처 : 유럽 질병 예방 및 통제 센터
  • 비고 : R를 이용하여 실시간 다운로드

 

 

Download today’s data on the geographic distribution of COVID-19 cases worldwide

The downloadable data file is updated daily and contains the latest available public data on COVID-19. You may use the data in line with ECDC’s copyright policy.

www.ecdc.europa.eu

 

 

[자료 처리 방안 및 활용 분석 기법]

  • 없음

 

[사용법]

  • 소스 코드 참조

 

[사용 OS]

  • Windows 10

 

[사용 언어]

  • R v3.6.3
  • R Studio v1.2.5033

 

 소스 코드

[명세]

  • 전역 설정
    • 최대 10 자리 설정
    • 메모리 해제
    • 영어 인코딩 설정
    • 폰트 설정
# Set Option
memory.limit(size = 9999999999999)
options(digits = 10)
Sys.setlocale("LC_TIME", "english")
font = "Palatino Linotype"

 

  • 라이브러리 읽기
# Library Load
library(extrafont)
library(tidyverse)
library(modelr)
library(magrittr)
library(lubridate)
library(gam)
library(spData)
library(sf)
library(cowplot)
library(utils)
library(httr)

 

  • 코로나 자료 다운로드
    • GET를 통해 실시간 csv 다운로드
# download the dataset from the ECDC website to a local temporary file
GET("https://opendata.ecdc.europa.eu/covid19/casedistribution/csv", authenticate(":", ":", type="ntlm"), write_disk(tf = tempfile(fileext = ".csv")))

 

  • csv 파일 읽기
# read the Dataset sheet into “R”. The dataset will be called "data".
dfData = read.csv(tf)

dplyr::glimpse(dfData)

 

 

  • Data Frame을 이용한 L1 전처리 
    • dplyr::filter를 통해 대한민국 (KR) 설정
    • readr::parse_date를 통해 문자열을 날짜형으로 변환
    • arrange를 통해 날짜형으로 정렬 그리고 사망자수 누적합 (nDeath) 계산
# L1 Processing Using Data Frame
dfDataL1 = dfData %>%
   dplyr::filter(geoId == "KR") %>%
   dplyr::mutate(
      dtDate = readr::parse_date(as.character(dateRep), "%d/%m/%Y")
   ) %>%
   dplyr::arrange(dtDate) %>%
   dplyr::mutate(
      nDeath = cumsum(deaths)
   )

dplyr::glimpse(dfDataL1)

 

 

  • 가시화
    • 데이터 세트에서 정보는 여전히 숨겨져 있기 때문에 가시화 필요
    • 가시화는 일반적인 정적 탐색 데이터 분석에서 웹 브라우저의 동적 대화식 데이터 시각화에 이르기까지 다양함
    • 특히 R의 기본 plot으로 여러 미학적 측면을 제어 할 수 있으나 Hadley Wickham (2016)이 개발한 ggplot2는 새로운 방법으로 시각화하기 때문에 이를 사용 

 

  • 가시화를 위한 초기 설정
  • 대만민국에서 코로나 19로 인한 누적 사망자수 시계열
sMinDate = as.Date(min(dfDataL1$dtDate, na.rm = TRUE) - 1)
sMaxDate = as.Date(max(dfDataL1$dtDate, na.rm = TRUE) + 3)

# Visualization Using ggplot2
ggplot(data = dfDataL1, aes(x = dtDate, y = nDeath)) +
   # cowplot::theme_minimal_grid() +
   theme_bw() +
   geom_point() +
   geom_line() + 
   scale_x_date(expand = c(0, 0), date_minor_breaks = "7 days", date_breaks = "7 days", date_labels = "%d %b", limits = as.Date(c(sMinDate, sMaxDate))) +
   scale_y_continuous(expand = c(0, 0), minor_breaks = seq(0, 300, 50), breaks = seq(0, 300, 50), limits = c(0, 300)) +
   labs(
      x = "Date [Day Month]"
      , y = "Cumulative Death"
      , fill = ""
      , colour = ""
      , title  = ""
      , subtitle = ""
      , caption = ""
   ) +
   theme(
      plot.title = element_text(face = "bold", size = 18, color = "black")
      , axis.title.x = element_text(face = "bold", size = 18, colour = "black")
      , axis.title.y = element_text(face = "bold", size =18, colour = "black", angle=90)
      , axis.text.x  = element_text(angle = 45, hjust = 1, face = "bold", size = 18, colour = "black")
      , axis.text.y  = element_text(face = "bold", size = 18, colour = "black")
      , legend.title = element_text(face = "bold", size = 14, colour = "white")
      , legend.position = "none"
      , legend.justification = c(0, 0.96)
      , legend.key = element_blank()
      , legend.text = element_text(size = 14, face = "bold", colour = "white")
      , legend.background = element_blank()
      , text = element_text(family = font)
      , plot.margin = unit(c(0, 12, 0, 0), "mm")
   ) + 
   ggsave(filename = paste0("FIG2/Img01_Using_ggplot2.png"), width = 10, height = 8, dpi = 600)

 

  • 지난 30일 동안 코로나 바이러스로 인한 사망자수는 선형적으로 증가
  • 2020년 02월 21일 이후에 최초 사망자 발생

그림. 대만민국에서 코로나 19로 인한 누적 사망자수 시계열.

 

  • Data Frame L1을 이용한 L2 전처리 
    • 예측 모형을 위해서 dplyr::filter를 통해 누적 사망자수 0 이상인 경우 필터
dfDataL2 = dfDataL1 %>%
   dplyr::filter(nDeath > 0)

dplyr::glimpse(dfDataL2)

 

 

  • Data Frame L2을 이용한 예측 모형 수행 
    • 코로나 바이러스로 사망자가 시간이 지남에 따라 선형적으로 증가하기 때문에 선형 및 비선형 모형을 사용
    • 다양한 회귀 모형 (선형, 2차 선형, 3차 선형 및 비선형)은 각각 lmgam으로 수행
    • 테스트 기간 (2020년 02월 01일 - 2020년 04월 06일)을 설정하여 데이터 프레임 (dfModel) 설정
Linear = lm(nDeath ~ dtDate, data = dfDataL2)
Quadratic = lm(nDeath ~ poly(dtDate, 2), data = dfDataL2)
Cubic = lm(nDeath ~ poly(dtDate, 3), data = dfDataL2)
Gam = gam(nDeath ~ s(dtDate), data = dfDataL2)

dfModel = dfDataL2 %>%
   modelr::data_grid(dtDate = modelr::seq_range(dtDate, nrow(dfDataL2))) %>%
   modelr::gather_predictions(Linear, Quadratic, Cubic, Gam)

dplyr::tbl_df(dfModel)

 

 

  • 테스트 기간에 대한 예측 및 검증 평가
    • cor 및 Metrics::rmse를 통해 상관계수 (r), 평균제곱근오차 (rmse)를 통해 검증 
    • 그 결과 1차 선형, 2차 선형, 3차 선형, Gam 순으로 검증 수치가 좋음 
dfModelL2 = dfModel %>%
   dplyr::left_join(dfDataL2, c("dtDate" = "dtDate")) %>%
   dplyr::group_by(model) %>%
   dplyr::summarise(
      r = cor(pred, nDeath)
      , rmse = Metrics::rmse(pred, nDeath)
   ) %>%
   dplyr::arrange(rmse, r)

dplyr::tbl_df(dfModelL2)

 

 

  • 가시화를 위한 초기 설정
  • 대만민국에서 코로나 19 자료를 이용한 누적 사망자수 모형 시계열
sMinDate = as.Date(min(dfDataL2$dtDate, na.rm = TRUE) - 1)
sMaxDate = as.Date(max(dfDataL2$dtDate, na.rm = TRUE) + 3)

ggplot(data = dfDataL2, aes(x = dtDate, y = nDeath)) +
   theme_bw() +
   geom_point(shape = 1, size = 2.2) +
   geom_line(data = dfModel, aes(x = dtDate, y = pred, col = model), size = 0.95) +
   scale_x_date(expand = c(0, 0), date_minor_breaks = "7 days", date_breaks = "7 days", date_labels = "%d %b", limits = c(sMinDate, sMaxDate)) +
   scale_y_continuous(expand = c(0, 0), minor_breaks = seq(0, 300, 50), breaks = seq(0, 300, 50), limits = c(0, 300)) +
   labs(
      x = "Date [Day Month]"
      , y = "Cumulative Death"
      , fill = ""
      , colour = ""
      , title  = ""
      , subtitle = ""
      , caption = ""
   ) +
   theme(
      plot.title = element_text(face = "bold", size = 18, color = "black")
      , axis.title.x = element_text(face = "bold", size = 18, colour = "black")
      , axis.title.y = element_text(face = "bold", size =18, colour = "black")
      , axis.text.x  = element_text(angle = 45, hjust = 1, face = "bold", size = 18, colour = "black")
      , axis.text.y  = element_text(face = "bold", size = 18, colour = "black")
      , legend.title = element_text(face = "bold", size = 14, colour = "white")
      , legend.position = "none"
      , legend.justification = c(0, 0.96)
      , legend.key = element_blank()
      , legend.text = element_text(size = 14, face = "bold", colour = "white")
      , legend.background = element_blank()
      , text = element_text(family = font)
      , plot.margin = unit(c(0, 12, 0, 0), "mm")
   ) +
   facet_wrap(~ model) + 
   ggsave(filename = paste0("FIG2/Img02_Using_ggplot2.png"), width = 10, height = 8, dpi = 600)

 

그림. 대만민국에서 코로나 19 자료를 이용한 누적 사망자수 모형 시계열.

 

  • 예측 기간에 대한 예측
    • 현재 기간을 기준으로 14일 (2주)을 예측 기간 (dfPredData) 설정
    • modelr::gather_predictions를 통해 해당 기간에 대해 누적 사망자수 시뮬레이션
dtStartDate = lubridate::ymd(dfDataL2$dtDate[nrow(dfDataL2)]) + lubridate::days(1)
dtEndDate = dtStartDate + lubridate::days(14)

dfPredData = data.frame(dtDate = seq.Date(dtStartDate, dtEndDate, "1 days"))

dplyr::tbl_df(dfPredData)

dfPredDataL1 = dfPredData %>%
   modelr::gather_predictions(Cubic, Linear, Gam, Quadratic)

dplyr::tbl_df(dfPredDataL1)

 

 

 

  • 해당 기간 (2020-04-07 - 2020-04-21) 동안 대한민국에서  코로나 19 자료를 이용한 누적 사망자수 시뮬레이션 결과
    • Gam 모형 결과 14일 이후 262명 사망자를 예측
Date Linear Quadratic Cubic Gam
2020-04-07 183 199 195 193
2020-04-08 187 206 200 198
2020-04-09 192 212 205 203
2020-04-10 196 219 210 208
2020-04-11 200 226 216 213
2020-04-12 205 232 221 218
2020-04-13 209 239 226 223
2020-04-14 213 246 231 228
2020-04-15 218 253 236 233
2020-04-16 222 261 241 238
2020-04-17 226 268 245 243
2020-04-18 231 275 250 248
2020-04-19 235 283 255 252
2020-04-20 240 290 259 257
2020-04-21 244 298 264 262

 

 

  • 가시화를 위한 초기 설정
  • 해당 기간 (2020-04-07 - 2020-04-21) 동안 대한민국에서  코로나 19 자료를 이용한 누적 사망자수 시뮬레이션 시계열
sMinDate = as.Date(min(dfDataL2$dtDate, na.rm = TRUE) - 1)
sMaxDate = as.Date(max(dfDataL2$dtDate, na.rm = TRUE) + 3)

ggplot(data = dfDataL2, aes(x = dtDate, y = nDeath)) +
   theme_bw() +
   geom_point(shape = 1, size = 2.2) +
   geom_line(data = dfModel, aes(x = dtDate, y = pred, col = model), size = 0.95) +
   scale_x_date(expand = c(0, 0), date_minor_breaks = "7 days", date_breaks = "7 days", date_labels = "%d %b", limits = c(sMinDate, sMaxDate)) +
   scale_y_continuous(expand = c(0, 0), minor_breaks = seq(0, 300, 50), breaks = seq(0, 300, 50), limits = c(0, 300)) +
   labs(
      x = "Date [Day Month]"
      , y = "Cumulative Death"
      , fill = ""
      , colour = ""
      , title  = ""
      , subtitle = ""
      , caption = ""
   ) +
   theme(
      plot.title = element_text(face = "bold", size = 18, color = "black")
      , axis.title.x = element_text(face = "bold", size = 18, colour = "black")
      , axis.title.y = element_text(face = "bold", size =18, colour = "black")
      , axis.text.x  = element_text(angle = 45, hjust = 1, face = "bold", size = 18, colour = "black")
      , axis.text.y  = element_text(face = "bold", size = 18, colour = "black")
      , legend.title = element_text(face = "bold", size = 14, colour = "white")
      , legend.position = "none"
      , legend.justification = c(0, 0.96)
      , legend.key = element_blank()
      , legend.text = element_text(size = 14, face = "bold", colour = "white")
      , legend.background = element_blank()
      , text = element_text(family = font)
      , plot.margin = unit(c(0, 12, 0, 0), "mm")
   ) +
   facet_wrap(~ model) + 
   ggsave(filename = paste0("FIG2/Img02_Using_ggplot2.png"), width = 10, height = 8, dpi = 600)

 

그림. 해당 기간 (2020-04-07 - 2020-04-21) 동안 대한민국에서 코로나 19 자료를 이용한 누적 사망자수 시뮬레이션 시계열.

 

[전체]

 

 

 

 참고 문헌

[논문]

  • 없음

[보고서]

  • 없음

[URL]

  • 없음

 

 문의사항

[기상학/프로그래밍 언어]

  • sangho.lee.1990@gmail.com

[해양학/천문학/빅데이터]

  • saimang0804@gmail.com

 

 

 

 

 

 

 

 

 

 

 

 

 

 

본 블로그는 파트너스 활동을 통해 일정액의 수수료를 제공받을 수 있음