Lovetoken

저는 개발 취향을 가진 데이터 분석가 Jr. 입니다.

Navigation
 » Home
 » About Me
 » Github

R에서 ggplot2 패키지를 이용한 간단한 Choropleth Map 구현하기

14 Oct 2016 » R, Data_Visualization



단계 구분도 - Choropleth Map

데이터 시각화를 주제로 모습을 자주 보이는 단계 구분도 (Choropleth Map)에 대해서 알아보고자 한다.
Choropleth map은 지역당 특정주제의 통계치를 활용해 시각적인 요소를 가미하여 나타낸 지도로서, 예시를 하나 들자면 국가별 인구의 밀도를 수치에 따라 색깔의 농도를 달리하여 나타내는 지도로 들 수 있다.

그림으로 표현하면 다음과 같다.



꽤 괜찮은 데이터 지도(data map)를 그려주는 Natural Breaks란?

이런 단계구분도를 R을 이용해 구현해 본 예제는 아래와 같다.

R Graphics Cookbook [Programming Insight] - 300page



R을 이용한 간단한 예제 실습

위 예제로 든 것을 실제로 만들어 보며 실습을 해보았다.
R의 여러 패키지의 도움을 빌렸다.
“maps”, “dplyr”, ““ggplot2” 3개의 패키지 도움을 빌리기 위해 로드한다.

# install.packages("maps")
# install.packages("dplyr")
# install.packages("ggplot2")
library("ggplot2")
library("maps")
library("dplyr")

“maps” 패키지에는 지도를 그리기 위한 위도, 경도 및 이에 매칭되는 나라에 대한 정보를 데이터프레임셋으로 만들 수 있도록 해주는데,
모든 나라의 지도정보가 담겨있으므로 Choropleth map 으로 그리고 싶은 나라를 서브세팅하여 전처리하는 것이 가능하다.
그래픽 엔진으로는 “ggplot2” 패키지를 선택해 Choropleth map을 구현해 볼 것이며,
“dplyr” 패키지는 데이터 전처리의 간편함수들을 이용하기 위함이다.

바로 위에 예시로 그린 나라는 미국이다.
미국만을 서브세팅 하여 그리는 예제만 해보고자 한다.

map_data() 는 해당지도의 경도, 위도, 지역, 지역명, 지도의 다각형을 그릴 수 있게 해 주는 서브정보들이 담겨있는 데이터프레임을 반환시켜주는데 ggplot2 패키지의 함수임을 유의하며 사용했다.

states_map <- map_data("state")

map_data 의 첫 번째 인자를 "state" 로 하여 미국의 주 시에 대한 정보의 데이터프레임을 states_map 명칭의 객체로 저장했다.
참고로 "state" 는 미국의 주, "world" 는 전세계, "france" 는 프랑스 지도 정보가 반환된다.

head(states_map, n = 20)
##         long      lat group order  region subregion
## 1  -87.46201 30.38968     1     1 alabama      <NA>
## 2  -87.48493 30.37249     1     2 alabama      <NA>
## 3  -87.52503 30.37249     1     3 alabama      <NA>
## 4  -87.53076 30.33239     1     4 alabama      <NA>
## 5  -87.57087 30.32665     1     5 alabama      <NA>
## 6  -87.58806 30.32665     1     6 alabama      <NA>
## 7  -87.59379 30.30947     1     7 alabama      <NA>
## 8  -87.59379 30.28655     1     8 alabama      <NA>
## 9  -87.67400 30.27509     1     9 alabama      <NA>
## 10 -87.81152 30.25790     1    10 alabama      <NA>
## 11 -87.88026 30.24644     1    11 alabama      <NA>
## 12 -87.92037 30.24644     1    12 alabama      <NA>
## 13 -87.95475 30.24644     1    13 alabama      <NA>
## 14 -88.00632 30.24071     1    14 alabama      <NA>
## 15 -88.01778 30.25217     1    15 alabama      <NA>
## 16 -88.01205 30.26936     1    16 alabama      <NA>
## 17 -87.99486 30.27509     1    17 alabama      <NA>
## 18 -87.95475 30.27509     1    18 alabama      <NA>
## 19 -87.90318 30.28082     1    19 alabama      <NA>
## 20 -87.82870 30.28655     1    20 alabama      <NA>

데이터의 앞부분 일부를 보니,
“alabama” 지역의 다각형을 그리기 위한 경도(long), 위도(lat) 정보가 있는 것을 볼 수 있다.
물론 alabama 만 있는 것이 아니라 수많은 미국의 주 region 이 존재하는 데이터이다.
이를 ggplot2 패키지를 이용해 구체화 시키는 코드를 아래와 같이 작성해 보았다.

ggplot(states_map, aes(long, lat, group = group)) + 
  geom_polygon(color = "black", fill = "gray") +
  coord_map("polyconic")

ggplot() 의 첫번째 인자에는 본체 데이터를 입력하고, 두번째 인자에 aes(x = long, y = lat) 을 지정하여 위도, 경도를 각각 x축과 y축에 매칭시킨다.
다음으로 geom_polygon()coord_map() 함수를 통해 다각형을 그리는 명령을 넣어 구체화 시키면 ggplot2 packages를 이용한 결과물이 위와 같이 나오게 된다.

그런데 위의 결과물은 단지 지도의 형태만을 볼 수 있고,
주시내별 어떠한 정보도 담겨있지 않은 공통된 회색이기 때문에
choropleth map 이라고 할 수 없는 상태이다.
주시내별 어떠한 정보를 담기 위하여 R의 내장데이터인 USArrests 를 활용해 보았다.

head(USArrests)
##            Murder Assault UrbanPop Rape
## Alabama      13.2     236       58 21.2
## Alaska       10.0     263       48 44.5
## Arizona       8.1     294       80 31.0
## Arkansas      8.8     190       50 19.5
## California    9.0     276       91 40.6
## Colorado      7.9     204       78 38.7

USArrests 객체는 미국의 주시내별 폭력∙범죄율 정보를 담고 있는 data.frame 빌트인 객체이다.
이를 이용하여 미국의 어떠한 마을에 범죄율이 강하고 적은지를 쉽게 확인할 수 있는 choropleth map 을 만들어 보면 의미 있는 결과물이 나올 것이라 예상된다.
앞에서 사용했던 미국 주시내별 지도위치정보를 담은 데이터프레임셋 states_map 를 다시 가지고 와서

states_map <- map_data("state")

region 변수와 내장데이터셋 USArrests 의 region 변수를 merge() 함수를 이용해 병합해 보았다.

crime_map <- data.frame(region = tolower(rownames(USArrests)), USArrests) %>%
    merge(states_map, by = "region")
head(crime_map)
##    region Murder Assault UrbanPop Rape      long      lat group order
## 1 alabama   13.2     236       58 21.2 -87.46201 30.38968     1     1
## 2 alabama   13.2     236       58 21.2 -87.48493 30.37249     1     2
## 3 alabama   13.2     236       58 21.2 -87.95475 30.24644     1    13
## 4 alabama   13.2     236       58 21.2 -88.00632 30.24071     1    14
## 5 alabama   13.2     236       58 21.2 -88.01778 30.25217     1    15
## 6 alabama   13.2     236       58 21.2 -87.52503 30.37249     1     3
##   subregion
## 1      <NA>
## 2      <NA>
## 3      <NA>
## 4      <NA>
## 5      <NA>
## 6      <NA>

이렇게 만들어진 crime_map 객체의 헤더부분을 살펴보면
region 변수에 따른 Murder, Assault, UrbanPop, Rape 변수정보들이 붙여진 것을 확인할 수 있다.

arrange(crime_map, order) %>% 
  ggplot(aes(long, lat, group = group, fill = Murder)) + 
  geom_polygon() +
  coord_map("polyconic") +
  scale_fill_continuous(low = "pink", high = "black")

arrange() 를 이용하여 order 변수 순으로 정렬을 해주었는데,
정렬을 시키는 이유는 올바른 다각형을 그리기 위함이다.
병합작업 시 원래 순서대로 정렬되어있던 것이 헝클어졌기 때문에 필요한 전처리 작업이다.
(정렬작업을 하지 않는다면 도저히 무슨 그림인지 알 수 없는 결과물이 나온다)

이후 ggplot()fill 인자를 Murder 변수로 지정하여 미국의 주시내별 살인범죄수에 따라 색깔의 농도가 진해지는 결과물을 출력하면 되겠다.
위의 결과물과 맨 첫 번째 소개했던 결과물이 같은 것을 확인할 수 있다.