학습 목표
- 제18대 대통령선거 투표결과를 시각화하여 이해한다.
2012년도 대통령 선거 투표결과 데이터는 중앙선거관리위원회 홈페이지에서 다운로드 받을 수 있다.
중앙선거관리위원회 → 분야별 정보 → 선거정보 → 하단 자료실
공간정보를 활용하여 18대 대선 투표결과를 시각화하는데 많은 팩키지가 동원된다.
# 0. 환경설정-------------------------------------------
library(tidyverse)
library(readxl)
library(ggmap)
library(maps)
library(maptools)
library(RColorBrewer)
library(scales)
library(rgdal)
library(rgeos)
library(maptools)
library(gpclib)
library(tmap)
library(viridis)
library(stringr)
library(xts)
library(zoo)
#gpclibPermit()
지리정보를 시각화할 경우 지도데이터(.shp
)와 투표결과데이터(엑셀 파일, 선관위 배포 기준)가 필요하다.
지도데이터는 그 시점에 맞는 행정지도를 받아 활용한다. 최신 행정구역(SHP) 다운로드 받을 때, 투표 주제도를 시각화할 단위를 시도, 시군구, 읍면동, 리 기준에 맞춰 미리 결정한다.
# 1. 지도 가져오기-------------------------------------------
korea_sido_shp <- readShapeSpatial("data/shapefile_sido/TL_SCCO_CTPRVN.shp", verbose=TRUE,
proj4string=CRS("+proj=tmerc +lat_0=38 +lon_0=127 +k=1 +x_0=955000 +y_0=2000000
+ellps=GRS80 +units=m +no_defs"))
Shapefile type: Polygon, (5), # of Shapes: 17
Shapefile type: Polygon, (5), # of Shapes: 17
지도데이터와 마찬가지로 선관위 홈페이지에서 다운로드 한 엑셀 파일을 지도데이터에 맞춰 가공한다.
# 2. 데이터 가져오기-------------------------------------------
## 2.1. 대선 투표 데이터 --------------------------------------
dat <- read_excel("data/제18대 대선 투표구별 개표자료.xls", sheet="대통령", skip=4)
names(dat) <- c("sido", "sigun", "emd", "vote_station", "polls", "votes", "pgh", "mji","etc_01", "etc_02", "etc_03", "etc_04","subtlt", "invalid", "abstain")
glimpse(dat)
Observations: 18,122
Variables: 15
$ sido <chr> "전국", "서울특별시", "서울특별시", "서울특별시", "서울특별시", "서울특별시"...
$ sigun <chr> "합계", "합계", "종로구", "종로구", "종로구", "종로구", "종로구", "종...
$ emd <chr> NA, NA, "소계", "재외투표", "국내부재자투표", "소계", "청운효자동", N...
$ vote_station <chr> NA, NA, NA, NA, NA, NA, "소계", "청운효자동제1투", "청운효자동제...
$ polls <dbl> 40507842, 8393847, 141447, 2138, 2689, 136620, 11...
$ votes <dbl> 30721459, 6307869, 103189, 1626, 2507, 99052, 890...
$ pgh <dbl> 15773128, 3024572, 49422, 798, 1167, 47457, 4233,...
$ mji <dbl> 14692632, 3227639, 52747, 807, 1274, 50662, 4598,...
$ etc_01 <dbl> 12854, 3559, 73, 1, 2, 70, 4, 1, 3, 0, 4, 2, 2, 0...
$ etc_02 <dbl> 16687, 3793, 86, 0, 3, 83, 10, 4, 3, 3, 5, 2, 3, ...
$ etc_03 <dbl> 53303, 11829, 211, 5, 6, 200, 18, 8, 4, 6, 10, 4,...
$ etc_04 <dbl> 46017, 5307, 97, 6, 7, 84, 4, 1, 2, 1, 2, 1, 1, 2...
$ subtlt <dbl> 30594621, 6276699, 102636, 1617, 2459, 98556, 886...
$ invalid <dbl> 126838, 31170, 553, 9, 48, 496, 40, 8, 15, 17, 20...
$ abstain <dbl> 9786383, 2085978, 38258, 512, 182, 37568, 2698, 9...
dat <- dat %>% dplyr::filter(sigun !="합계") %>%
mutate(emd = na.locf(emd)) %>%
dplyr::filter(emd != "소계") %>%
mutate(vote_station = ifelse(is.na(vote_station), paste0(emd, "_", sigun), vote_station)) %>%
dplyr::filter(vote_station != "소계") %>% ungroup
by_sido <- dat %>% dplyr::group_by(sido) %>%
dplyr::summarise(polls_tlt = sum(polls),
votes_tlt = sum(votes),
pgh_tlt = sum(pgh),
mji_tlt = sum(mji),
invalid_tlt = sum(invalid),
abstain_tlt = sum(abstain)) %>%
mutate(vote_diff = pgh_tlt - mji_tlt) %>% ungroup
names(by_sido) <- c("CTP_KOR_NM", "votes_tlt", "ballot_tlt", "pgh",
"mji", "invalid_tlt", "abstain_tlt", "vote_diff")
# 3. 지도 데이터 병합(@data 방식)-------------------------------------------
sido_vote_shp <- merge(korea_sido_shp, by_sido, by='CTP_KOR_NM')
투표 결과를 각 시도별로 viridis
색상을 활용하여 총투표수를 시각화한다.
# 4. 주제도 시각화(tmap)-------------------------------------------
## 4.1. 전체 -------------------------------
pal10 <- viridis(10, option="D")
tm_shape(sido_vote_shp) +
tm_fill("ballot_tlt",
style = "kmeans",
title = "총투표",
palette=pal10,
n=10) +
tm_borders(alpha=.7, lwd=2) +
tm_layout(outer.margins=0, asp=0, scale=.8)
투표결과를 facet
기능을 활용하여 각 시도별로 나눠 살펴볼 수도 있다. 각 시도 수준에서는 큰 의미는 없지만, 이런 기능도 가능하다는 정도로 살펴본다.
## 4.2. Facet -------------------------------
pal10 <- viridis(10, option="D")
# tmap_mode("plot")
tm_shape(sido_vote_shp) +
tm_fill("ballot_tlt",
style = "kmeans",
title = "총투표",
palette=pal10,
n=10) +
tm_borders(alpha=.7, lwd=2) +
tm_facets(by="CTP_KOR_NM", free.coords=TRUE) +
tm_layout(legend.show = FALSE, outer.margins=0)
박근혜, 문재인 두 후보 투표수를 나란히 지리정보를 활용하여 비교할 경우 grid
팩키지의 도움을 받아 구현한다. 박근혜 후보 투표수 주제도, 문재인 후보 투표수 주제도를 객체로 저장해 놓고서 grid
팩키지를 활용하여 한장의 그림을 완성한다.
## 4.3. 박근혜 vs 문재인 -------------------------------
## 박근혜 문재인 투표 나란히 비교
# tmap_mode("plot")
pal10 <- viridis(6, option="D")
pgh_tmap <- tm_shape(sido_vote_shp) +
tm_fill("pgh",
style = "fixed",
title = "박근혜",
palette=pal10,
breaks=c(seq(0,3000000, by=500000))) +
tm_borders(alpha=.7, lwd=2) +
tm_layout(outer.margins=0, asp=0, scale=.8)
mji_tmap <- tm_shape(sido_vote_shp) +
tm_fill("mji",
style = "fixed",
title = "문재인",
palette=pal10,
breaks=c(seq(0,3000000, by=500000))) +
tm_borders(alpha=.7, lwd=2) +
tm_layout(outer.margins=0, asp=0, scale=.8)
## 나란히 한장에 찍기
library(grid)
grid.newpage()
pushViewport(viewport(layout=grid.layout(1,2)))
print(pgh_tmap, vp=viewport(layout.pos.col = 1))
print(mji_tmap, vp=viewport(layout.pos.col = 2))
박근혜, 문재인 두 후보간 표차이를 leaflet
기능을 활용하여 인터랙티브하게 작성한다. tmap
에는 tmap_mode(“plot”) 모드로 정적 공간정보 시각화 방식과 tmap_mode(“view”) 모드를 활용하여 인터랙티브 공간정보 분석이 가능하다.
## 4.3. 표차이 분석 : 박근혜 - 문재인 -------------------------------
pal10 <- brewer.pal(10, "RdYlBu")
# 박근혜 vs. 문재인 인터랙티브 팝업
vote_diff_tmap <- tm_shape(sido_vote_shp) +
tm_fill("vote_diff",
style = "kmeans",
palette=pal10,
n=10,
title=c("표차이", "표차이", "박근혜", "문재인"),
popup.vars=c("CTP_KOR_NM", "vote_diff", "pgh", "mji")) +
tm_borders(alpha=.7, lwd=2) +
tm_layout(outer.margins=0, asp=0, scale=.8)
tmap_mode("view")
vote_diff_tmap