2  데이터 과학 큰 그림

데이터 과학을 각 부분별로 나눠서 상세히 살펴보는 대신 데이터 과학을 구성하는 데이터 가져오기(Import), 깔끔화(Tidy), 변환(Transform), 시각화(visualize)에 대해 전체적인 작업흐름을 신속히 일별하고 시작하는 것이 최근의 추세다. 다양한 데이터에 대한 이해와 분석 경험이 쌓이면서 tidyverse가 새롭게 출현했고, 관련하여 데이터 문법(grammar of data), 그래프 문법(grammar of graphics), 표 문법(grammar of table)이 tidyverse의 중추를 이룬다. 각각을 자세히 살펴보기에 앞서 데이터 과학 맛보기를 통해 전반적인 흐름을 살펴보자.

graph TB
    subgraph Software["<strong>좋은 소프트웨어 개발(사람) + 챗GPT(인공지능)</strong>"]
        subgraph 이해하기
            모형 --> 시각화
            변환 --> 모형
            시각화 --> 변환
            
        end
    가져오기 --> 깔끔화 --> 이해하기
    이해하기 --> 의사소통

    AI["챗GPT(LLM)"]

    end
    
    classDef modern fill:#fff,stroke:#333,stroke-width:2px,color:#333,font-family:MaruBuri,font-size:12px;
    classDef emphasize fill:#8CBDE3,stroke:#333,stroke-width:3px,color:#333,font-family:MaruBuri,font-size:15px,font-weight:bold;
    classDef subgraphStyle fill:#f0f8ff,stroke:#333,stroke-width:2px,color:#333,font-family:MaruBuri,font-size:15px;
    
    class 모형 modern
    class 가져오기,깔끔화,변환,시각화,의사소통 emphasize
    class 이해하기 subgraphStyle
그림 2.1: 챗GPT 데이터 과학 큰 그림

백의 천사로도 잘 알려진 플로렌스 나이팅게일 사례는 데이터 과학의 전체 과정(whole game)을 잘 보여주는 대표적인 사례다. 나이팅게일은 단순히 데이터를 수집하고 분석하는 것에 그치지 않고, 데이터에서 얻은 통찰을 실제 세계에 적용하여 변화를 이끌어냈기 때문이다.

나이팅게일은 크림 전쟁 당시 병원에서 데이터를 수집하고 분석하여 사망 원인의 대부분이 열악한 위생 환경에서 비롯된 감염성 질병이라는 사실을 발견했다. 하지만 발견한 것에서 만족하지 않고 열악한 병원 환경 개선을 위한 캠페인을 펼쳤다.

이 과정에서 나이팅게일은 수집된 소중한 데이터를 시각화하여 설득력 있게 전달하는 방법을 고민했고, 그 결과 로즈 다이어그램(Rose Diagram)이라는 새로운 형태의 시각화 그래프를 고안해냈다. 이는 당시로서는 획기적인 데이터 시각화 방식이었으며, 최고 의사결정권자인 여왕은 물론 일반 대중에게 데이터의 의미를 쉽게 이해할 수 있도록 커뮤니케이션에 적극 활용되었다.

나이팅게일의 노력은 병원 내 사망률을 크게 낮추는 성과로 이어졌고, 군 의료 체계 전반의 개혁으로 이어져 수많은 소중한 생명을 살렸을 뿐만 아니라, 공중보건에 대한 사회적 인식을 높이고, 간호사의 전문성을 향상시키는 계기가 되었다.

이처럼 나이팅게일의 사례는 데이터 수집, 분석, 시각화, 그리고 실제 행동과 변화까지, 데이터 과학의 전 과정을 포괄하고 있다. 데이터 과학이 단순히 데이터를 다루는 기술이 아니라, 데이터를 통해 세상을 이해하고 변화시키는 전체적인 과정임을 잘 보여주는 사례라고 할 수 있다. 따라서 데이터 과학을 배우는 모두에게 나이팅게일의 사례는 데이터 과학 전 과정을 짧은 시간에 이해하는 데 좋은 출발점이 될 것이다.

2.1 나이팅게일 신화탄생

크림 전쟁은 1853년부터 1856년까지 일어난 큰 전쟁이었다. 한쪽에는 러시아, 반면 다른 한쪽에는 영국, 프랑스, 오스만 제국(현대 튀르키예), 그리고 나중에 사르디니아(현대 이탈리아의 일부)가 동맹을 구성하여 전쟁을 치렀다. 전쟁이 바로 시작된 이유는 러시아가 오스만 제국 내 정교회 신자들을 보호하려는 명분을 내세웠지만, 사실 더 많은 영토를 차지하기 위함이었다. 양측 간 전쟁은 흑해를 두고 남하하는 러시아에 맞서 동맹군이 크림반도에서 발생하여 “크림전쟁”(Crimean War)으로 불린다. 영화로 소개된 경기병대의 돌격(“Charge of the Light Brigade”), 영국 간호사 플로렌스 나이팅게일의 활약, 전신과 철도의 본격적인 도입으로 큰 의미를 갖는 전쟁이기도 하다. 많은 전투와 많은 사람들이 죽은 후, 1856년 파리 조약으로 전쟁은 마무리되어, 러시아의 확장은 잠시 멈추게 되었고, 오스만 제국도 한숨 돌린 계기가 되었다.

크림 전쟁 중 스쿠타리 막사는 튀르키예(구 터키)의 스쿠타리 병원(Scutari Hospital, Turkey)이 영국 군 병원으로 개조되었다. 크림전쟁에서 부상을 당한 수많은 병사가 치료를 위해 이곳으로 보내졌지만, 병자와 부상병들을 감당할 수 있도록 설계되지 않았고 제대로 된 역할도 수행하지 못했다. 1854년 나이팅게일이 간호사 일행과 함께 도착했을 때, 비위생적인 환경과 고통받는 병사들을 보고 경악했다. 나이팅게일의 스쿠타리 병원에서의 경험은 병원과 의료 서비스를 개선하여 이와 같은 고통과 비극이 재발하지 않도록 향후 프로젝트의 중요한 동기와 방향이 되었다.

그림 2.2: 스쿠타리 병원의 한 병동 석판화 그림 (William Simpson)

환자의 사망률을 42%에서 2%로 낮추고 집중치료실(ICU)을 설치하여 상태가 중한 환자를 격리하여 집중 관리하는 등 근대적인 간호체계를 수립하는 데 기여했다.

2.1.1 원본 데이터

크림 전쟁 중 튀르키예의 스쿠타리 병원에서 몇 년간에 걸쳐 수작업으로 종이에 분석 가능한 형태의 자료를 만들어내는 것은 결코 쉬운 작업이 아니었다.

그림 2.3: 원본 데이터

2.1.2 그래프 진화

복잡한 논거를 제시하는 대신 구체적인 주장에 데이터 시각화와 데이터 스토리텔링(Storytelling)을 통해 청중에 한걸음 더 다가섰다. 나이팅게일의 스토리텔링은 열악한 위생 상태와 과밀로 인해 불필요한 죽음이 얼마나 많이 발생하는지 이해하기 쉬운 비교를 통해 이야기를 구성해서 설득해 나갔다. 예를 들어, 군대 사망률을 민간인 사망률(유사한 환경의 맨체스터)과 비교하는 프레임을 제시하고, 군대 막사에서 생활하는 평시 병사들이 비슷한 연령대 민간인 남성보다 더 높은 비율로 사망하는 것을 제시했다. 이를 통해, 데이터가 보여주는 현실을 부정할 수 없게 만들었고, 군대 행정에 극적인 개혁을 이끌어냈다. 1

(a) 막대그래프
(b) 맨체스터 사망

빅토리아 여왕 보고(I)

빅토리아 여왕 보고(II)

빅토리아 여왕 보고(III)
그림 2.4: 나이팅게일 그래프 진화과정

2.1.3 설득

나이팅게일은 크림 전쟁 중 병원에서의 위생 문제와 관련된 데이터를 수집하고 분석하여 그 결과를 시각화했고, 병원에서의 사망 원인 중 대부분이 감염성 질병으로 인한 것임을 발견했다. 이러한 감염성 질병은 부적절한 위생 조건과 밀접한 관련이 있음을 확인했다.

나이팅게일은 병원의 위생 상태 개선을 통해 수많은 생명을 구할 수 있다는 사실을 확인했고, 연구 결과와 권장 사항을 다양한 영국 정부 부처에 제출했으며, 특히 1858년에 영국의 장관들에게 보고서를 제출했다. 이를 통해서 군 병원의 위생 조건을 개선하는 데 큰 영향을 미쳤다.

그림 2.5: 나이팅게일과 빅토리아 여왕

2.1.4 성과와 영향

나이팅게일 캠페인이 민간 공중보건에 미친 가장 큰 영향은 실현되기까지 오랜 기간에 걸쳐 다각도로 검토되었고, 마침내 1875년 영국 공중보건법(British Public Health Act)에 법제화되었다. 이 법에는 잘 정비된 하수도, 깨끗한 수돗물, 건축법 규제 등의 요건이 담겨있다. 질병에 대한 면역력을 강화하는 백신과 농작물 수확량을 획기적으로 늘리는 인공비료 개발과 함께이 제도적인 노력으로 평균 수명을 두 배로 늘리는 원동력이 되었다.

2.2 작업과정

2.2.1 디지털 데이터

스페인 R-ladies GitHub 저장소 rladies/spain_nightingale에서 엑셀 형태로 된 데이터를 가져와서 전처리 작업을 진행한다.

library(tidyverse)
library(readxl)

death_raw <- read_excel("data/datos_florence.xlsx", sheet = "Sheet1", skip = 1)

death_tbl <- death_raw |> 
  janitor::clean_names() |> 
  set_names(c("Month", "Army", "Disease", "Wounds", "Other", "Disease.rate", "Wounds.rate", "Other.rate")) |> 
  mutate(Date = lubridate::my(Month)) |> 
  separate(Month, into = c("Month", "Year"), sep = " |_") |> 
  select(Date, Month, Year, everything()) 

death_tbl
#> # A tibble: 24 × 10
#>    Date       Month Year   Army Disease Wounds Other Disease.rate Wounds.rate
#>    <date>     <chr> <chr> <dbl>   <dbl>  <dbl> <dbl>        <dbl>       <dbl>
#>  1 1854-04-01 Apr   1854   8571       1      0     5          1.4         0  
#>  2 1854-05-01 May   1854  23333      12      0     9          6.2         0  
#>  3 1854-06-01 Jun   1854  28333      11      0     6          4.7         0  
#>  4 1854-07-01 Jul   1854  28722     359      0    23        150           0  
#>  5 1854-08-01 Aug   1854  30246     828      1    30        328.          0.4
#>  6 1854-09-01 Sep   1854  30290     788     81    70        312.         32.1
#>  7 1854-10-01 Oct   1854  30643     503    132   128        197          51.7
#>  8 1854-11-01 Nov   1854  29736     844    287   106        341.        116. 
#>  9 1854-12-01 Dec   1854  32779    1725    114   131        632.         41.7
#> 10 1855-01-01 Jan   1855  32393    2761     83   324       1023.         30.7
#> # ℹ 14 more rows
#> # ℹ 1 more variable: Other.rate <dbl>

HistDate 패키지에 동일한 데이터셋이 잘 정제되어 있어 이를 바로 활용해도 좋다.

library(HistData)

HistData::Nightingale |> 
  as_tibble()
#> # A tibble: 24 × 10
#>    Date       Month  Year  Army Disease Wounds Other Disease.rate Wounds.rate
#>    <date>     <ord> <int> <int>   <int>  <int> <int>        <dbl>       <dbl>
#>  1 1854-04-01 Apr    1854  8571       1      0     5          1.4         0  
#>  2 1854-05-01 May    1854 23333      12      0     9          6.2         0  
#>  3 1854-06-01 Jun    1854 28333      11      0     6          4.7         0  
#>  4 1854-07-01 Jul    1854 28722     359      0    23        150           0  
#>  5 1854-08-01 Aug    1854 30246     828      1    30        328.          0.4
#>  6 1854-09-01 Sep    1854 30290     788     81    70        312.         32.1
#>  7 1854-10-01 Oct    1854 30643     503    132   128        197          51.7
#>  8 1854-11-01 Nov    1854 29736     844    287   106        341.        116. 
#>  9 1854-12-01 Dec    1854 32779    1725    114   131        632.         41.7
#> 10 1855-01-01 Jan    1855 32393    2761     83   324       1023.         30.7
#> # ℹ 14 more rows
#> # ℹ 1 more variable: Other.rate <dbl>

2.2.2 데이터와 사투

앞서 준비한 death_tbl 데이터프레임에서 사망 관련 데이터를 처리하고 시각화하기 위한 전처리를 수행하여 시각화를 위한 준비작업을 수행한다. 먼저 Date, Disease.rate, Wounds.rate, Other.rate 칼럼을 선택하고, pivot_longer 함수를 사용해 시각화에 적합한 데이터로 재구조화한다. str_replace_all 함수를 사용하여 칼럼 이름에서 “.rate”를 제거하고, ifelse 함수를 이용해 날짜를 기준으로 나이팅게일 팀이 준비한 방식을 적용하기 전과 후의 “이전”과 “이후” 체제로 구분한다. factor 함수를 사용하여 범주 순서를 정의하고, 마지막으로 month 함수를 이용해 날짜에서 해당 월을 추출하고 death_viz에 저장한다.

death_viz <- death_tbl %>% 
  select(Date, Disease.rate, Wounds.rate, Other.rate) %>% 
  pivot_longer(-Date, names_to = "사망원인", values_to = "사망자수") |> 
  mutate(사망원인 = str_replace_all(사망원인, "\\.rate", ""), 
         체제 = ifelse(Date <= as.Date("1855-03-01"), "조치이전", "조치이후")) %>% 
  mutate(체제 = factor(체제, levels = c("조치이전", "조치이후"))) %>%  
  mutate(해당월 = month(Date, label = TRUE, abbr = TRUE)) |> 
  mutate(사망원인 = case_when(사망원인 == "Disease" ~ "질병",
                              사망원인 == "Wounds" ~ "부상",
                              사망원인 == "Other" ~ "기타")) |> 
  mutate(사망원인 = factor(사망원인, levels = c("질병", "부상", "기타")))

death_viz
#> # A tibble: 72 × 5
#>    Date       사망원인 사망자수 체제     해당월
#>    <date>     <fct>       <dbl> <fct>    <ord> 
#>  1 1854-04-01 질병          1.4 조치이전 4     
#>  2 1854-04-01 부상          0   조치이전 4     
#>  3 1854-04-01 기타          7   조치이전 4     
#>  4 1854-05-01 질병          6.2 조치이전 5     
#>  5 1854-05-01 부상          0   조치이전 5     
#>  6 1854-05-01 기타          4.6 조치이전 5     
#>  7 1854-06-01 질병          4.7 조치이전 6     
#>  8 1854-06-01 부상          0   조치이전 6     
#>  9 1854-06-01 기타          2.5 조치이전 6     
#> 10 1854-07-01 질병        150   조치이전 7     
#> # ℹ 62 more rows

2.3 시각화

‘ggplot2’ 패키지를 이용하여 크림전쟁 나이팅게일 활약상을 담은 데이터를 시각화한다. 나이팅게일 활약 전과 후로 데이터(death_viz)를 나눠 “크림전쟁 병사 사망원인”에 대한 극좌표계 시각화를 통해 이해하기 쉬운 설득력 있는 시각화 결과물을 제시하고 있다. 추가적으로, ‘showtext’ 패키지로 구글 “Noto Serif KR” 글꼴을 선택 적용하고, ‘hrbrthemes’ 라이브러리를 이용하여 뒷배경 검정색을 사용하여 붉은색 질병으로 인한 사망자 수의 확연한 감소를 시각적으로 강조한다.

library(hrbrthemes) 
library(showtext)
showtext.auto()
font_add_google(name = "Noto Serif KR", family = "noto_serif")
noto_font <- "noto_serif"

death_gg <- death_viz %>% 
  ggplot(aes(x = 해당월, y = 사망자수, fill = 사망원인)) +
  geom_col(color = "grey20") + 
  theme_modern_rc(base_family = noto_font, subtitle_family = noto_font) + 
  scale_fill_manual(values = c("firebrick", "orange", "#365181"), name = "") +
  scale_y_sqrt() +
  facet_wrap(~ 체제) + 
  coord_equal(ratio = 1) +  
  coord_polar() +
  labs(title = "크림전쟁 병사 사망원인", 
       subtitle = "데이터 시각화와 커뮤니케이션", 
       caption = "데이터 출처: 크림전쟁 사망자") + 
  theme(legend.position = "top", 
        text = element_text(family = noto_font, size = 18),
        axis.title.y = element_blank(),
        axis.title.x = element_blank(),
        axis.ticks = element_blank(),
        axis.text.x   = element_text(family = "MaruBuri", color = "white", size = 50),
        axis.text.y   = element_text(family = "MaruBuri", color = "white", size = 50),
        plot.margin = unit(rep(0.7, 4), "cm"),
        plot.title = element_text(color = "white", family = noto_font, size = 100),
        plot.subtitle = element_text(color = "grey70", size = 70),
        plot.caption = element_text(color = "grey70", family = noto_font, size = 54),
        legend.title = element_text(color = "white", size = 70),
        legend.text = element_text(color = "white", size = 55),
        strip.text = element_text(color = "white", size = 80, face = "bold", family = noto_font, hjust = 0.5))

death_gg

ragg::agg_jpeg("images/viz_death_gg.jpeg", width = 10, height = 7, units = "in", res = 600)
death_gg
dev.off()
그림 2.6: 크림전쟁 병사 사망원인 조치전후 시각화

2.3.1 선그래프

나이팅게일은 간호 분야의 선구자로 잘 알려져 있지만, 통계학자로서 “콕스콤(CoxComb)” 또는 “장미 다이어그램”(Rose Diagram)으로 알려진 원그래프를 제시하였다. 그러나 현재는 시간의 흐름에 따라 병사 사망자 수 변화를 조치 전후로 명확히 하는 방법으로 선그래프가 기본 기법으로 자리 잡고 있다.

death_new_gg <- death_viz |> 
  ggplot(aes(x = Date, y = 사망자수, color = 사망원인)) +
    geom_line() +
    geom_point() +
    geom_vline(xintercept = as.Date("1855-03-15"), linetype= 2) +
    theme_ipsum_pub(base_family = noto_font, subtitle_family = noto_font) +
    labs(title = "크림전쟁 병사 사망원인", 
         subtitle = "데이터 시각화와 커뮤니케이션", 
         caption = "데이터 출처: 크림전쟁 사망자",
         x = "월일") + 
    scale_y_continuous(labels = scales::comma, limits = c(0, 1150)) +
    theme(legend.position = "top", 
          text = element_text(family = noto_font, size = 35),
          axis.ticks = element_blank(),
          plot.margin = unit(rep(0.7, 4), "cm"),
          axis.title.x   = element_text(family = "MaruBuri", size = 45),
          axis.title.y   = element_text(family = "MaruBuri", size = 45),
          axis.text.x    = element_text(family = "MaruBuri", size = 35),
          axis.text.y    = element_text(family = "MaruBuri", size = 35),
          plot.title = element_text(color = "black", family = noto_font, size = 100),
          plot.subtitle = element_text(color = "black", family = noto_font, size = 80),
          plot.caption = element_text(color = "grey10", family = noto_font, size = 37),
          legend.text = element_text(color = "black", size = 45)) +
    geom_segment(x = as.Date("1854-03-01"), y = 1100,
                 xend = as.Date("1855-03-01"), yend = 1100,
                 color = "gray70",
                 arrow = arrow(length = unit(0.1, "inches"))) +
    geom_segment(x = as.Date("1855-04-01"), y = 1100,
                 xend = as.Date("1856-03-01"), yend = 1100,
                 color = "gray15",
                 arrow = arrow(length = unit(0.1, "inches"))) +
    annotate("text", x = as.Date("1854-09-01"), y = 1140, label = "조치이전",
             size = 20.5, color = "gray30", family = noto_font) +
    annotate("text", x = as.Date("1855-09-01"), y = 1140, label = "조치이후",
             size = 20.5, color = "gray15", family = noto_font)          

death_new_gg

ragg::agg_jpeg("images/death_new_gg.jpeg", width = 10, height = 7, units = "in", res = 600)
death_new_gg
dev.off()
그림 2.7: 크림전쟁 병사 사망원인 조치전후 선 그래프

2.3.2 막대그래프

동일한 정보를 막대그래프를 통해 시각화할 수도 있다. 원그래프와 비교하여 보면 명확하게 사망자 수를 직관적으로 비교할 수 있다는 점에서 큰 장점이 있다.

death_bar_gg <- death_viz |> 
  ggplot() +
    geom_col(aes(x = Date, y = 사망자수, fill = 사망원인), colour="white") +
    geom_vline(xintercept = as.Date("1855-03-15"), linetype= 2) +
    scale_fill_manual(values = c("firebrick", "orange", "#365181")) + 
    # theme_ipsum_pub(base_family = noto_font, subtitle_family = noto_font) +
    labs(title = "크림전쟁 병사 사망원인", 
         subtitle = "데이터 시각화와 커뮤니케이션", 
         caption = "데이터 출처: 크림전쟁 사망자",
         x = "월일") + 
    scale_y_continuous(labels = scales::comma, limits = c(0, 1150)) +
    theme(legend.position = "top", 
          text = element_text(family = noto_font, size = 35),
          axis.ticks = element_blank(),
          plot.margin = unit(rep(0.7, 4), "cm"),
          axis.title.x   = element_text(family = "MaruBuri", size = 45),
          axis.title.y   = element_text(family = "MaruBuri", size = 45),
          axis.text.x    = element_text(family = "MaruBuri", size = 35),
          axis.text.y    = element_text(family = "MaruBuri", size = 35),
          plot.title = element_text(color = "black", family = noto_font, size = 100),
          plot.subtitle = element_text(color = "black", family = noto_font, size = 80),
          plot.caption = element_text(color = "grey10", family = noto_font, size = 37),
          legend.title = element_text(color = "black", size = 70),
          legend.text = element_text(color = "black", size = 45)) +
    geom_segment(x = as.Date("1854-03-01"), y = 1100,
                 xend = as.Date("1855-03-01"), yend = 1100,
                 color = "gray70",
                 arrow = arrow(length = unit(0.1, "inches"))) +
    geom_segment(x = as.Date("1855-04-01"), y = 1100,
                 xend = as.Date("1856-03-01"), yend = 1100,
                 color = "gray15",
                 arrow = arrow(length = unit(0.1, "inches"))) +
    annotate("text", x = as.Date("1854-09-01"), y = 1140, label = "조치이전",
             size = 8.5, color = "gray30", family = noto_font) +
    annotate("text", x = as.Date("1855-09-01"), y = 1140, label = "조치이후",
             size = 8.5, color = "gray15", family = noto_font) 

death_bar_gg

ragg::agg_jpeg("images/death_bar_gg.jpeg", width = 10, height = 7, units = "in", res = 600)
death_bar_gg
dev.off()
그림 2.8: 크림전쟁 병사 사망원인 조치전후 막대 그래프

2.4 표 문법

데이터 문법, 그래프 문법에 이어 최근 “표 문법”이 새롭게 자리를 잡아가고 있다. 표 문법에 맞춰 나이팅게일 크림전쟁 사망자 수를 조치 이전과 조치 이후로 나눠 요약하면 확연한 차이를 파악할 수 있다.

gtgtExtras 패키지를 활용하여 death_viz 데이터프레임을 사망 원인별 사망자 수를 “조치 이전”과 “조치 이후”로 구분하여 표를 두 개 생성한다. 각 표는 날짜, 질병, 부상, 기타 범주로 사망자 수와 그 합계를 표시하며, 총 사망자 수가 250명을 초과하는 행에 대한 강조 색상을 입히고 나서 두 표를 나란히 배치하여 조치 전후 효과를 시각적으로 비교한다.

library(gt)
library(gtExtras)
library(patchwork)

before_tbl <- death_viz |> 
  filter(체제 == "조치이전")

after_tbl <- death_viz |> 
  filter(체제 == "조치이후")

before_gt <- before_tbl |> 
  pivot_wider(names_from = 사망원인, values_from = 사망자수) |> 
  select(날짜 = Date, 질병, 부상, 기타) |> 
  mutate(합계 = 질병 + 부상 + 기타) |> 
  gt() |> 
    gt_theme_538() |> 
    cols_align("center") |> 
    fmt_integer( columns = 질병:합계) |> 
    tab_spanner(label = "조치 이전", columns = c(질병, 부상, 기타)) |> 
    data_color(
      columns = c(질병, 부상, 기타, 합계),
      rows = 합계 > 250,      
      method = "numeric",
      palette = "ggsci::red_material")

after_gt <- after_tbl |> 
  pivot_wider(names_from = 사망원인, values_from = 사망자수) |> 
  select(날짜 = Date, 질병, 부상, 기타) |> 
  mutate(합계 = 질병 + 부상 + 기타) |> 
  gt() |> 
    gt_theme_538() |> 
    cols_align("center") |> 
    fmt_integer( columns = 질병:합계) |> 
  tab_spanner(label = "조치 이후", columns = c(질병, 부상, 기타)) |> 
  data_color(
    columns = c(질병, 부상, 기타, 합계),
    rows = 합계 > 250,      
    method = "numeric",
    palette = "ggsci::red_material")

# before_gt |> 
#    gtsave("before_gt.png", path = "images")
# after_gt  |> 
#    gtsave("after_gt.png", path = "images")

library(cowplot)
p111 <- ggdraw() + draw_image("images/before_gt.png", scale = 1.0)
p112 <- ggdraw() + draw_image("images/after_gt.png", scale = 0.9)
plot_grid(p111, p112)
그림 2.9: 조치 전후 변화를 표 시각화

2.5 요약

플로렌스 나이팅게일은 크림 전쟁 중 병원에서의 열악한 위생 상태와 감염성 질병으로 인한 높은 사망률을 데이터 수집과 분석을 통해 발견했다. 데이터를 통해 발견한 사실을 시각화하여 정부와 대중에게 효과적으로 전달함으로써 군 병원 위생 개선을 이끌어냈고, 사망률을 크게 낮춰 수많은 소중한 생명을 구하는 성과로 이어졌다.

나이팅게일은 수집한 데이터를 분석하고 시각화하는 과정에서 로즈 다이어그램이라는 새로운 형태의 그래프를 고안하였다. 당시로서는 혁신적인 데이터 시각화 방식이었으며, 데이터의 의미를 명확하게 전달하는 데 큰 역할을 했다. 더 나아가 데이터 스토리텔링 기법을 활용하여 군대 사망률과 민간인 사망률을 비교하는 등 설득력 있는 주장을 펼쳤다.

나이팅게일의 활동은 단순히 군 병원의 개선에 그치지 않고, 이후 영국 공중보건 정책에도 큰 영향을 미쳤다. 이러한 노력은 1875년 공중보건법 제정으로 이어졌으며, 하수도 정비, 수질 관리, 건축법 규제 등 공중보건 인프라 개선의 기반이 되었다.

나이팅게일의 사례는 데이터 수집, 분석, 시각화를 통해 실제 변화를 이끌어낸 데이터 과학의 전형적인 예시라고 할 수 있다. 데이터에 기반한 통찰력으로 사회 문제를 파악하고, 이를 효과적으로 전달하여 정책 변화와 개선을 이끌어냈다는 점에서 데이터 과학이 단순히 기술적인 분석에 그치는 것이 아니라, 실제 세상에 긍정적인 영향을 미칠 수 있음을 보여주는 대표적인 사례로 알려져 있다.


  1. 출처: How Florence Nightingale Changed Data Visualization Forever - The celebrated nurse improved public health through her groundbreaking use of graphic storytelling↩︎