1. 광역단체장 지방선거 시각화를 위한 사전 준비

현시점 대한민국 제7회 지방 선거가 얼마 남지 않았다. 제6회 지방선거결과를 최근에 발전된 공간데이터 분석 기법을 적용하여 데이터를 분석해 보자. 최근 tidyverse 데이터 분석 체계에 맞춰 공간지리정보를 분석하는데 사전 준비가 필요하다.

  1. 지도 파일: .shp 파일
  2. 행정동 코드: 엑셀 파일
  3. 광역단체장 선거 데이터: 위키백과 사전 대한민국_제6회_지방_선거 - 광역자치단체장

제6회 지방선거 광역단체장

지리데이터도 tidyverse 체계에 맞춰 데이터 분석 전략을 수립했으니 이제 앞서 정의한 데이터를 구해보자.

  1. 지도 피일: 대한민국 최신 행정구역(SHP) 다운로드
  2. 행정동 코드: 행정표준코드관리시스템 접속하여 상단 자주묻는질문 “행정동코드(전체) 및 법정동·행정동코드 매핑 자료 받는 방법은 어떻게 되나요?”을 참조
  3. 광역단체장 선거 데이터: 위키백과 사전 대한민국_제6회_지방_선거 - 광역자치단체장
    • rvest 팩키지를 통해 데이터를 긁어온다.

2. 광역단체장 선거결과 공간정보 시각화

2.1. 팩키지 설치

sf 팩키지가 핵심적인 역할을 수행한다. 따라서 devtools::install_github("r-spatial/sf") 명령어를 통해 팩키지를 설치한다. GDAL이 설치되지 않아 sf 팩키지가 설치되지 않는 경우 다음 유튜브 동영상을 참조하여 깔끔히 설치를 마무리한다.

ggplotgeom_sf()가 설치가 되지 않는 경우 devtools::install_github("tidyverse/ggplot2", force=TRUE) 설치해 보는 것도 문제점을 해결해 나가는 방법이 된다.

# 0. 환경설정 ---------
# library(tidyverse)
# library(readxl)
# library(stringr)
# library(ggplot2)
# library(sf)
# library(pryr)
# library(rvest)
# library(ggpubr)
# library(extrafont)
# loadfonts()
# library(tmap)

2.2. 데이터 가져오기

지도 데이터를 비롯한 행정코드, 광역단체장 선거결과 데이터를 순차적으로 불러 읽어 드린다. 데이터를 읽어오는 과정에서 필요한 데이터 전처리 작업도 함께 수행한다.

# 1. 데이터 가져오기 ----------------
## 1.1. 지도 데이터 다운로드 --------

# url <- "http://www.gisdeveloper.co.kr/download/admin_shp/CTPRVN_201703.zip"
# download.file(url, destfile = "data/sido.zip")
# unzip(zipfile = "data/sido.zip", exdir = "data/sido")

## 1.2. shp 파일 불러오기 --------
sido_shp <- st_read("data/sido/TL_SCCO_CTPRVN.shp")
## Reading layer `TL_SCCO_CTPRVN' from data source `D:\webzen\spatial\data\sido\TL_SCCO_CTPRVN.shp' using driver `ESRI Shapefile'
## Simple feature collection with 17 features and 3 fields
## geometry type:  MULTIPOLYGON
## dimension:      XY
## bbox:           xmin: 746110.3 ymin: 1458754 xmax: 1387950 ymax: 2066200
## epsg (SRID):    NA
## proj4string:    +proj=tmerc +lat_0=38 +lon_0=127.5 +k=0.9996 +x_0=1000000 +y_0=2000000 +ellps=GRS80 +units=m +no_defs
sido_shp$CTP_KOR_NM <- iconv(sido_shp$CTP_KOR_NM, from = "CP949", to = "UTF-8", sub = NA, mark = TRUE, toRaw = FALSE)

head(sido_shp)
## Simple feature collection with 6 features and 3 fields
## geometry type:  MULTIPOLYGON
## dimension:      XY
## bbox:           xmin: 746110.3 ymin: 1671909 xmax: 1164120 ymax: 2001987
## epsg (SRID):    NA
## proj4string:    +proj=tmerc +lat_0=38 +lon_0=127.5 +k=0.9996 +x_0=1000000 +y_0=2000000 +ellps=GRS80 +units=m +no_defs
##   CTPRVN_CD CTP_ENG_NM CTP_KOR_NM                       geometry
## 1        11      Seoul 서울특별시 MULTIPOLYGON (((965666.5034...
## 2        26      Busan 부산광역시 MULTIPOLYGON (((1157412.229...
## 3        27      Daegu 대구광역시 MULTIPOLYGON (((1107777.593...
## 4        28    Incheon 인천광역시 MULTIPOLYGON (((847834.7470...
## 5        29    Gwangju 광주광역시 MULTIPOLYGON (((932712.6874...
## 6        30    Daejeon 대전광역시 MULTIPOLYGON (((990946.7248...
## 1.3. 시군 코드 --------
sido_cd_df <- read_excel("data/jscode/jscode20171218/KIKcd_H.20171218.xlsx", sheet="KIKcd_H")
sido_cd_df <- sido_cd_df %>% 
    mutate(CTPRVN_CD = str_sub(행정동코드, 1,2)) %>% 
    group_by(CTPRVN_CD) %>% 
    summarise(시도명 = first(시도명))

## 1.4. 지방자치단체장 --------

Sys.setlocale("LC_ALL", "English")
## [1] "LC_COLLATE=English_United States.1252;LC_CTYPE=English_United States.1252;LC_MONETARY=English_United States.1252;LC_NUMERIC=C;LC_TIME=English_United States.1252"
url <- "https://ko.wikipedia.org/wiki/%EB%8C%80%ED%95%9C%EB%AF%BC%EA%B5%AD_%EC%A0%9C6%ED%9A%8C_%EC%A7%80%EB%B0%A9_%EC%84%A0%EA%B1%B0" 

province_df <- url %>%
    read_html() %>%
    html_nodes(xpath='//*[@id="mw-content-text"]/div/table[4]') %>%
    html_table(fill = TRUE) %>% 
    .[[1]]

Sys.setlocale("LC_ALL", "Korean")
## [1] "LC_COLLATE=Korean_Korea.949;LC_CTYPE=Korean_Korea.949;LC_MONETARY=Korean_Korea.949;LC_NUMERIC=C;LC_TIME=Korean_Korea.949"
province_df <- province_df %>% 
    mutate(시도명 = str_replace_all(지역, "장$|지사$", ""))  %>% 
    filter(지역 != "투표율") %>% 
    mutate(득표수 = as.numeric(str_replace_all(득표수, ",", "")))

2.3. 데이터 병합

먼저 행정코드와 선거결과를 병합하고 나서, 그 다음으로 .shp 지도파일도 병합한다.

# 2. 데이터 병합 --------
## 2.1. 행정코드와 선거결과 병합
jibang_df <- inner_join(sido_cd_df, province_df, by="시도명")

## 2.2. 행정코드와 연결된 선거결과를 지도와 연결
sido_shp <- left_join(sido_shp, jibang_df, by="CTPRVN_CD")

2.4. 정적 시각화

st_simplify() 함수를 통해 빠른 시각화를 위해서 파일 크기를 줄이고 나서, ggplot 작업흐름에 맞춰 지방선거 결과를 시각화 한다.

# 3. 지리정보 시각화 --------
## 3.1. SHP 파일 크기 줄이기 --------
sido_simp_shp <- st_simplify(sido_shp, dTolerance = 100)

## 3.2. 정적 그래프 --------
ggplot(data=sido_simp_shp, aes(fill=득표수)) +
    geom_sf() +
    theme_pubr(base_family="NanumGothic") +
    labs(title="제6회 지방선거 - 광역단체장") + 
    theme(legend.position = "right") +
    scale_fill_gradient(low = "wheat1", high = "red", name = "득표수", labels = scales::comma)

2.5. 동적 시각화

tmap 팩키지를 활용하여 유사한 방식으로 동적 시각화 작업을 수행한다.

## 3.3. 동적 그래프 --------
tmap_mode("view")
tm_shape(sido_simp_shp) +
    # tm_polygons(col = "득표수") +
    tm_borders() +
    tm_fill("득표수",
            style = "kmeans",
            title=c("지역", "득표수", "득표율", "비고"),
            popup.vars=c("지역", "득표수", "득표율", "비고"))