1. 메르스 사태 1

메르스, 중동호흡기증후군은 2015년 5월 21일 사우디아라비아 등을 거쳐 바레인을 방문한 68세 남성이 첫 확진 진단은 이후 크나큰 사회문제와 함께 향후 숙제를 남겨주었다.

2. 메르스 네트워크 분석

NetMiner - MERS-CoV 웹사이트에 일자별로 데이터가 잘 정리되어 있다. 국문과 영문으로 두가지 언어로 제공되고 있으며 엑셀 파일을 메르스 네트워크 분석 데이터로 활용한다.

2.1. 메르스 데이터 환경설정

네트워크 분석을 위해서 필요한 데이터분석 연장을 준비한다. 데이터프레임으로 네트워크 분석에 필요한 데이터를 가져와서 graph_from_data_frame() 함수를 통해 igraph 객체로 변환하여 정적, 동적 네트워크 및 다양한 통계분석을 수행한다. 단, 데이터는 결점(Vertex, Node), 연결점(Edge, Link) 정보를 담고 있는 edgelist 형태로 자료구조를 사전에 정비해야만 된다.

메르스 데이터 분석 도구상자

# 0. 환경설정 ------------------

library(igraph)
library(tidyverse)
library(threejs)
library(readxl)
library(ggpubr)
library(forcats)
library(extrafont)
loadfonts()

2.2. 메르스 데이터

NetMiner - MERS-CoV에서 다운로드 받은 엑셀 파일에서 필요한 결점(Vertex, Node), 연결점(Edge, Link) 쉬트를 read_excel 함수를 통해 불러온다.

  • 결점(Vertex): (한국어)2015-10-02xlsx.xlsx“, sheet=”확진자"
  • 연결선(Edge): (한국어)2015-10-02xlsx.xlsx“, sheet=”확진자간 link"

그리고 나서 graph_from_data_frame() 함수를 통해 igraph 네트워크 객체를 생성하면 데이터 준비는 모두 끝났다.

# 1. 데이터 가져오기 ------
## 1.1. 데이터 읽어들이기
mers_vert <- read_excel("data/(한국어)2015-10-02xlsx.xlsx", sheet="확진자")
colnames(mers_vert) <-c("확진자", "성별", "나이", "확진일", "현상태", "현상태_판정일자", 
                        "감염병원", "감염지역", "감염 이유", "비고")

mers_edge <- read_excel("data/(한국어)2015-10-02xlsx.xlsx", sheet="확진자간 link")

## 1.2. 네트워크 데이터 변환
mers_ng <- graph_from_data_frame(d = mers_edge, vertices = mers_vert, directed = TRUE)

3. 메르스 데이터 분석 헬로우 월드

결점(Vertex)에서 성별을 뽑아 색상을 달리 한 후에 메르스 igraph 객체를 시각화해보자.

# 2. 네트워크 데이터 변환 ------

V(mers_ng)$color <- ifelse(V(mers_ng)$성별 == "f", "red", "blue")


# 3. 네트워크 데이터 변환 ------
plot(mers_ng,
     vertex.label.color = "black",
     vertex.label.cex = 0.8,
     vertex.size = 0,
     edge.color = 'black',
     edge.width = 1,
     edge.arrow.size = 0.1,
     layout = layout_nicely(mers_ng))

3.1. 메르스 데이터 탐색적 데이터 분석

메르스 감염 네트워크를 이해하기 필요한 기본적인 정보를 살펴본다. 먼저 네트워크 내 결점(Vertex, Node)와 연결선(Edge, Link) 갯수를 살펴본다. vcount, ecount도 있고, gorder, gsize 함수도 있지만 동일하다.

그리고, farthest_vertices, get_diameter 함수를 통해 네트워크 노드간 떨어진 거리도 파악한다.

# 2. 네트워크 기술통계 ------
## 2.1. 결점(Vertex, Node)와 연결선(Edge, Link) 갯수
vcount(mers_ng)
[1] 186
gorder(mers_ng)
[1] 186
gsize(mers_ng)
[1] 181
ecount(mers_ng)
[1] 181
## 2.2. 네트워크 크기

farthest_vertices(mers_ng) 
$vertices
+ 2/186 vertices, named, from c6d2e11:
[1] M00001 M00099

$distance
[1] 3
get_diameter(mers_ng)  
+ 4/186 vertices, named, from c6d2e11:
[1] M00001 M00014 M00050 M00099

3.2. 특정 결점(vertex) 기준

메르스 데이터는 양방향이 아니라 특정 환자가 다른 환자를 감염시키는 구조라 modeout만 의미가 있다.

  • ego() 함수를 통해 특정 결점(vertex), ‘M00014’ 환자와 떨어진 정도(2)를 지정하면 근처 결점을 확인할 수 있다.
  • incident() 함수는 특정 결점과 연결된 연결선을 확인하는데 도움을 준다.
ego(mers_ng, 2, 'M00014', mode = c('out'))
[[1]]
+ 95/186 vertices, named, from c6d2e11:
 [1] M00014 M00035 M00037 M00039 M00040 M00041 M00046 M00047 M00048 M00049
[11] M00050 M00055 M00056 M00057 M00058 M00059 M00060 M00061 M00062 M00063
[21] M00064 M00065 M00066 M00067 M00068 M00069 M00070 M00071 M00072 M00073
[31] M00074 M00075 M00076 M00077 M00078 M00079 M00080 M00081 M00089 M00090
[41] M00091 M00096 M00097 M00098 M00100 M00102 M00103 M00104 M00105 M00110
[51] M00111 M00112 M00113 M00114 M00116 M00118 M00120 M00121 M00122 M00123
[61] M00124 M00125 M00126 M00131 M00132 M00134 M00135 M00136 M00137 M00138
[71] M00139 M00140 M00142 M00146 M00177 M00099 M00162 M00164 M00133 M00145
[81] M00150 M00160 M00165 M00167 M00168 M00170 M00173 M00176 M00179 M00153
[91] M00175 M00147 M00186 M00169 M00181
incident(mers_ng, 'M00014', mode = c("all"))
+ 75/181 edges from c6d2e11 (vertex names):
 [1] M00014->M00035 M00014->M00037 M00014->M00039 M00014->M00040
 [5] M00014->M00041 M00014->M00046 M00014->M00047 M00014->M00048
 [9] M00014->M00049 M00014->M00050 M00014->M00055 M00014->M00056
[13] M00014->M00057 M00014->M00058 M00014->M00059 M00014->M00060
[17] M00014->M00061 M00014->M00062 M00014->M00063 M00014->M00064
[21] M00014->M00065 M00014->M00066 M00014->M00067 M00014->M00068
[25] M00014->M00069 M00014->M00070 M00014->M00071 M00014->M00072
[29] M00014->M00073 M00014->M00074 M00014->M00075 M00014->M00076
[33] M00014->M00077 M00014->M00078 M00014->M00079 M00014->M00080
[37] M00014->M00081 M00014->M00089 M00014->M00090 M00014->M00091
+ ... omitted several edges

3.3. 교차 결점(vertex) 파악

메르스 전파에서 중요한 역할을 한 ‘M00014’ 환자와 ‘M00001’ 환자 사이에 어떤 환자가 있는지 파악하는데 neighbors() 함수로 특정 네트워크를 떼어내고 나서, intersection() 함수를 사용하게 되면 중간 매개환자도 쉽게 파악할 수 있다.

## 2.3. 교차 결점
mers_14 <- neighbors(mers_ng, 'M00014', mode = c('all'))
mers_01 <- neighbors(mers_ng, 'M00001', mode = c('all'))

intersection(mers_14, mers_01)
+ 1/186 vertex, named, from c6d2e11:
[1] M00037

4. 메르스 중요환자(Vertex) 식별

네트워크가 크면 중요 결점(vertex)를 시각적으로 식별하는 것이 쉽지는 않다. 이런 경우 degree() 함수를 사용해서 나가는 도수(Out Degree)를 통계량으로 설정하여 일반적인 결점과 중요한 결점을 파악한다.

# 3. 핵심 결점(vertex) 식별 ------
## 3.1. 나가는 도수(Out Degree) 기준 중요 결점 식별
mers_outd <- degree(mers_ng, mode = c("out"))
table(mers_outd)
mers_outd
  0   1   2   3   6  10  23  31  74 
155  17   7   2   1   1   1   1   1 
which.max(mers_outd)
M00014 
    14 
## 3.2. 나가는 도수 히스토그램
mers_outd_df <- data.frame(mers_outd)
mers_outd_df$mers_id <- row.names(mers_outd_df)

mers_outd_df %>% 
  rename(연결중앙성 = mers_outd) %>% 
  ggplot(aes(x=연결중앙성)) +
    geom_density() +
    labs(x="외부로 나가는 연결중앙성", y="밀도") +
    theme_pubr(base_family = "NanumGothic")

4.1. 메르스 중요환자(Vertex) 시각화

make_ego_graph() 함수를 통해 특정 노드 나가는 도수가 가장 큰 값을 갖는 ’M00014’를 중심으로 그래프를 생성하고 나서, 이에 대한 거리를 계산한다. 그리고 거리를 각 노드에 넣어 시각화를 완성한다.

## 3.3. 나가는 도수 거리별 시각화

M00014 <- make_ego_graph(mers_ng, diameter(mers_ng), nodes = 'M00014', mode = c("all"))[[1]]
mers_dists <- distances(M00014, "M00014")

colors <- c("black", "red", "orange", "blue")
V(M00014)$color <- colors[mers_dists+1]

plot(M00014, 
     vertex.label = mers_dists, 
     vertex.label.color = "white",
     vertex.label.cex = 1,
     edge.color = 'black',
     vertex.size = 5,
     edge.arrow.size = .05,
     main = "메르스 최초 환자로부터 거리(Geodesic Distances)")

4.2. 메르스 중요환자(Vertex) 고유값 기준 시각화

고유값 중앙성(eigen_centrality)을 기준으로 중요 결점을 파악하고 이를 시각화하는 것도 가능하다.

# 4. 고유값 기준 ---------------
mers_ng_ec <- eigen_centrality(mers_ng)
which.max(mers_ng_ec$vector)
M00014 
    14 
plot(mers_ng,
     vertex.label.color = "black", 
     vertex.label.cex = 0.8,
     vertex.size = 20*(mers_ng_ec$vector),
     edge.color = 'gray88',
     edge.arrow.size = .05,
     main = "메르스 전파 중요 환자 - 고유값 중심점 기준"
)

5. 메르스 병원 시각화

네트워크 시각화에 메르스 병원을 시각화하는 경우 먼저 V(mers_ng)$color에 색상을 정의한다. fct_lump() 함수를 사용하면 손쉽게 범주를 나눌 수 있다.

# 5. 병원 시각화 ------
V(mers_ng)$color <- fct_lump(V(mers_ng)$감염병원, 7)

plot(mers_ng, 
     vertex.label = V(mers_ng)$감염병원, 
     vertex.label.color = "black",
     vertex.label.cex = 0.9,
     vertex.label.family="NanumGothic",
     edge.color = 'black',
     vertex.size = 5,
     edge.arrow.size = .05,
     main = "메르스 감염병원")

6. 인터랙티브 메르스 감염 시각화

동적(static), 정적(dynamic), 인터랙티브(interactive) 네트워크 시각화 팩키지가 다수 존재한다. R Base 그래픽 시스템에 기초한 계열과 최근 그래프 문법(grammar of graphcis)에 기초한 계열 이 정적그래프에 존재하고, 동적, 인터랙티브, 애니메이션 계열이 별도로 존재한다.

graphjs(mers_ng,
        vertex.shape = V(mers_ng)$name,
        vertex.size = 0.1,
        edge.color = 'darkgray',
        main = "메르스 전파 네트워크"
)

  1. 데이터저널리즘, 메르스 사태를 한눈에_KBS 성재호 기자