제 18 대 대통령선거 시각화

제 18 대 대통령선거는 보수와 진보가 하나로 뭉쳐 일대일 대결을 펼쳤다. 하지만, 대부분이 사람들은 수도권에 모여 투표를 했지만, 이를 지리정보를 통해 표현할 경우 오히려 왜곡된 정보가 언론에 전달되고 있다고 주장하는 분도 있고, 그들의 주장을 들어보면 일리도 있다.

환경설정

shapefile을 갖고 지리정보 시각화하는 팩키지를 불러온다.

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

library(rgdal)
library(ggplot2)
library(rgdal)
library(rgeos)
library(ggmap)
library(maps)
library(maptools)
library(RColorBrewer)
library(scales)
library(tidyverse)
library(readxl)
library(gridExtra)

데이터 가져오기

엑셀로 된 제18대 대선 투표구별 개표자료를 불러오고, shapefile로 된 시도별 지도를 불러와서 박근혜 후보와 문재인 후보 득표수 및 득표차에 대한 데이터를 준비한다.

# 1. 데이터 가져오기 -----------------------------------------------------------------
# 1.1. 지도데이터 가져오기 -------------------------------------------------------------
kor_sp <- rgdal::readOGR(dsn=file.path("data/shapefile_sido/", "TL_SCCO_CTPRVN.shp"), verbose=TRUE)
OGR data source with driver: ESRI Shapefile 
Source: "data/shapefile_sido//TL_SCCO_CTPRVN.shp", layer: "TL_SCCO_CTPRVN"
with 17 features
It has 3 fields
kor_sp$area <- gArea(kor_sp, byid=TRUE) / (1e6)

## 1.2. 2012년 대선 득표율 ---------------------------------------
vote_df <- read_excel("data/제18대 대선 투표구별 개표자료.xls", skip=3)
# http://stackoverflow.com/questions/28549045/dplyr-select-error-found-duplicated-column-name
valid_column_names <- make.names(names=names(vote_df), unique=TRUE, allow_ = TRUE)
names(vote_df) <- valid_column_names

names(vote_df) <- c("시도명", "구시군명", "읍면동명", "투표구명", "선거인수", "투표수", 
                    "박근혜", "문재인", "X.1", "X.2", "X.3", "X.4", "X.5", "무효.투표수", "기권수")

votes_df <- vote_df %>% 
  # dplyr::filter(`구시군명` =="합계" & `시도명` !="전국" & `시도명` !="세종특별자치시") %>%
  dplyr::filter(`구시군명` =="합계" & `시도명` !="전국" & `시도명` !="세종특별자치시") %>%
  dplyr::select(`시도명`, `선거인수`, `박근혜`, `문재인`) %>% 
  mutate_each(funs(as.numeric), matches("^[박|문|선]")) %>% 
  mutate(`표차`=`박근혜`-`문재인`)

## 1.3. 데이터 병합 ---------------------------------------
mapping_code <- read_excel("data/시도코드.xlsx")

votes_df <- full_join(votes_df, mapping_code, by=c("시도명"="CTP_KOR_NM"))
votes_df <- votes_df %>% mutate(CTPRVN_CD = factor(CTPRVN_CD)) %>% 
  mutate(`시도명` = factor(`시도명`))
glimpse(votes_df)
Observations: 17
Variables: 6
$ 시도명    <fctr> 서울특별시, 부산광역시, 대구광역시, 인천광역시, 광주광역시, 대전광역시, 울산광역시, 경기도, ...
$ 선거인수  <dbl> 8393847, 2911700, 1990746, 2241366, 1117781, 1182321, 88...
$ 박근혜    <dbl> 3024572, 1324159, 1267789, 852600, 69574, 450576, 41397...
$ 문재인    <dbl> 3227639, 882511, 309034, 794213, 823737, 448310, 275451...
$ 표차      <dbl> -203067, 441648, 958755, 58387, -754163, 2266, 138526,...
$ CTPRVN_CD <fctr> 11, 26, 27, 28, 29, 30, 31, 41, 42, 43, 44, 45, 46,...
votes_sp <- merge(kor_sp, votes_df)

득표정보 시각화

박근혜 대통령을 상징하는 색상을 붉은 계열로, 문재인 후보를 상징하는 색상을 푸른색 계열로 준비하고 spplot 함수를 활용하여 시각화한다.

# 2. 시각화 -------------------------------------------------------------------------
## 2.1. Original --------------------------------------------------------------------
park.palette <- brewer.pal(n = 9, name = "Reds")
moon.palette <- brewer.pal(n = 9, name = "Blues")
diff.palette <- brewer.pal(n = 9, name = "RdBu")

sp_label <- function(x, label) {list("sp.text", coordinates(x), label,cex=0.5)}

### 2.1.1. 박근혜 

spplot(votes_sp, zcol="박근혜", col.regions = park.palette, 
       cuts = length(park.palette)-1,
       sp.layout=sp_label(votes_sp, votes_sp$CTP_KOR_NM), 
       colorkey = list(space = "bottom", height = 1))

### 2.1.2. 문재인
spplot(votes_sp, zcol="문재인", col.regions = moon.palette, 
       cuts = length(moon.palette)-1,
       sp.layout=sp_label(votes_sp, votes_sp$CTP_KOR_NM), 
       colorkey = list(space = "bottom", height = 1))

### 2.1.3. 박근혜 - 문재인 표차
spplot(votes_sp, zcol="표차", col.regions = diff.palette, 
       cuts = length(diff.palette)-1,
       sp.layout=sp_label(votes_sp, votes_sp$CTP_KOR_NM), 
       colorkey = list(space = "bottom", height = 1))

### 2.1.4. 한번에 비교

grid.arrange(
  spplot(votes_sp, zcol="박근혜", col.regions = park.palette, 
         cuts = length(park.palette)-1,
         sp.layout=sp_label(votes_sp, votes_sp$CTP_KOR_NM), main="박근혜 득표수", 
         colorkey = list(space = "bottom", height = 1)),
  
  spplot(votes_sp, zcol="표차", col.regions = diff.palette, 
         cuts = length(diff.palette)-1,
         sp.layout=sp_label(votes_sp, votes_sp$CTP_KOR_NM), main="후보간 표차이", 
         colorkey = list(space = "bottom", height = 1)),
  
  spplot(votes_sp, zcol="문재인", col.regions = moon.palette, 
         cuts = length(moon.palette)-1,
         sp.layout=sp_label(votes_sp, votes_sp$CTP_KOR_NM), main="문재인 득표수", 
         colorkey = list(space = "bottom", height = 1)), nrow=1
)

시각화 원본 데이터

DT::datatable(votes_sp@data %>% dplyr::select(CTPRVN_CD, CTP_KOR_NM, area, 
                                                선거인수, 박근혜, 문재인, 표차)) %>% 
  DT::formatCurrency(c(3,4,5,6,7), currency="", interval = 3, mark=',', digits=0)

카토그램(Cartogram)

카토그램(cartogram, 변량비례도(變量比例圖))은 의석수나 선거인단수, 인구 등의 특정한 데이터 값의 변화에 따라 지도의 면적이 왜곡되는 그림으로 실제 보고자 하는 정보를 경우에 따라서는 더 잘 표현할 수도 있다.

환경설정

R에서 카토그램을 구현할 경우 Rcartogram, getcartr 팩키지를 설치해야 한다. 사전에 brew install fftw을 통해 맥을 사용하는 경우 fftw를 설치해야만 된다.

## 2.2. Cartogram --------------------------------------------------------------------
# devtools::install_github("omegahat/Rcartogram")
# devtools::install_github('chrisbrunsdon/getcartr',subdir='getcartr')
# X11(type='cairo')
library(Rcartogram)
library(getcartr)
## 2.2.1. 박근혜
park_carto <- quick.carto(spdf=votes_sp,v=votes_sp@data$박근혜,res=256)

png(filename="fig/park-carto.png", width = 1024)
spplot(park_carto, "박근혜", col.regions = park.palette, 
       cuts = length(park.palette)-1,
       # main="Park(박근혜 득표수)", 
       colorkey = list(space = "bottom", height = 1))
dev.off()

## 2.2.2. 문재인
moon_carto <- quick.carto(spdf=votes_sp,v=votes_sp@data$문재인, res=256)

png(filename="fig/moon-carto.png", width = 1024)
spplot(moon_carto, "문재인", col.regions = moon.palette, 
       cuts = length(moon.palette)-1, 
       # main="Moon(문재인 득표수)", 
       colorkey = list(space = "bottom", height = 1))
dev.off()

## 2.2.3. 유권자
voter_carto <- quick.carto(spdf=votes_sp,v=votes_sp@data$선거인수, res=256)

png(filename="fig/voter-carto.png", width = 1024)
spplot(voter_carto, "선거인수", col.regions = voter.palette, 
       cuts = length(voter.palette)-1, 
       # main="Voters(선거인수)", 
       colorkey = list(space = "bottom", height = 1))
dev.off()

### 2.2.4. 한번에 비교

png(filename="fig/park-moon-all-carto.png", width = 1024)
grid.arrange(
  spplot(park_carto, "박근혜", col.regions = park.palette, 
         cuts = length(park.palette)-1,
         # main="Park(박근혜 득표수)", 
         colorkey = list(space = "bottom", height = 1)),
  
  spplot(voter_carto, "선거인수", col.regions = voter.palette, 
         cuts = length(voter.palette)-1, 
         # main="Voters(선거인수)", 
         colorkey = list(space = "bottom", height = 1)),
  
  spplot(park_carto, "문재인", col.regions = moon.palette, 
         cuts = length(moon.palette)-1, 
         # main="Moon(문재인 득표수)", 
         colorkey = list(space = "bottom", height = 1)), nrow=1
)
dev.off()

박근혜 득표 카토그램

문재인 득표 카토그램

박근혜, 문재인, 선거권자 카토그램