1 제7회 지방선거 1

제7회 지방선거는 더불어민주당의 압승으로 막을 내렸고, 그 후폭풍으로 야당을 중심으로 정계개편에 대한 논의가 오고가고 있다.

1.1 제7회 지선 데이터

위키백과사전 제7회_전국동시지방선거 페이지에서 지방선거 데이터를 가져올 수 있다. 그리고, 유권자수를 대신하여 위키백과 대한민국 행정구역 페이지에서 광역시도별 인구수를 가져올 수 있다.

데이터는 광역의원 비례대표 정당별 득표를 가져와서 이를 바탕으로 정당별 비례대표 투표수를 상관분석과 네트워크 시각화 분석 재료로 삼는다.

rvest 팩키지로 데이터를 가져와서 정제 작업을 수행하여 깔끔한 데이터프레임으로 저장한다.

# 0. 환경설정 -----
library(tidyverse)
library(rvest)
library(glue)
library(curl)
library(corrplot)
library(corrr)
library(tidygraph)
library(ggraph)
library(extrafont)
loadfonts()

# 1. 데이터 -----
# Sys.setlocale("LC_ALL", "C")
## 1.1. 제 7 회 지방선거 여론조사 -----
seven_url <- "https://ko.wikipedia.org/wiki/제7회_전국동시지방선거"

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

## 1.2. 광역 시도별 인구  -----
pop_url <- "https://ko.wikipedia.org/wiki/대한민국의_행정_구역"

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

# Sys.setlocale("LC_ALL", "Korean")

# 2. 데이터 정제 -----
## 2.1. 지방선거 데이터 정제
seven_df <- seven_dat %>% 
    gather(정당, 득표수, -지역) %>% 
    filter(!str_detect(지역, "전국"),
           !str_detect(정당, "기타|합계")) %>% 
    mutate(득표수 = str_replace_all(득표수, "\\,|\\.", "") %>% as.integer) %>% 
    filter(정당 %in% c("더불어민주당", "자유한국당", "정의당", "바른미래당", "민주평화당")) %>% 
    as_tibble()

## 2.2. 광역시도 인구 데이터 정제
pop_df <- pop_dat %>% 
    select(지역=`행정 구역`, 인구) %>% 
    filter(!str_detect(지역, "계")) %>% 
    mutate(지역 = abbreviate(지역, minlength=2)) %>% 
    mutate(지역 = case_when(str_detect(지역, "충청북") ~ "충북",
                          str_detect(지역, "충청남") ~ "충남",
                          str_detect(지역, "전라북") ~ "전북",
                          str_detect(지역, "전라남") ~ "전남",
                          str_detect(지역, "경상북") ~ "경북",
                          str_detect(지역, "경상남") ~ "경남",
                          TRUE ~ 지역)) %>% 
    mutate(인구 = str_replace_all(인구, "\\,|\\.", "") %>% as.integer) %>% 
    as_tibble()

상관분석

1.2 상관분석 2

광역시도별 정당별 데이터를 정제하였다면 corrr 팩키지를 통해 cor() 함수로 상관계수 행렬을 데이터프레임으로 변환한 후 몇가지 함수로 수월하게 상관계수행렬을 다룰 수 있다.

shave(), rearrange(), stretch(), fashion() 함수를 익혀두면 유용하게 사용할 수 있다.

## 2.2. 상관계수 행렬
seven_cor_df <- seven_df %>% 
    spread(지역, 득표수, fill=0L) %>% 
    as.data.frame() %>% 
    column_to_rownames(var="정당") %>% 
    correlate() %>% 
    rearrange()

seven_cor_df %>% 
    as.data.frame() %>% 
    column_to_rownames(var="rowname") %>% 
    replace(., is.na(.), 1) %>% 
    as.matrix() %>% 
    corrplot.mixed(., upper="ellipse")

1.3 네트워크 시각화

상관계수 행렬을 stretch() 함수로 변환시킨 후에 이를 as_tbl_graph() 함수로 네트워크 객체로 변환시키고 나서, 이를 ggraph를 통해 시각화한다.

## 2.3. 네트워크 그래프
### 2.3.1. 네트워크 그래프 데이터 변환: 상관계수행렬 --> 네트워크 from to 
seven_nw_df <- seven_cor_df %>% 
    stretch(na.rm = TRUE) %>% 
    arrange(-r)

seven_nw <- as_tbl_graph(seven_nw_df, directed=FALSE)

### 2.3.1. 네트워크 그래프 데이터 변환
seven_nw %>% 
    activate(nodes) %>% 
    filter(!str_detect(name, "세종")) %>% 
    left_join(pop_df, by=c("name" = "지역")) %>% 
    # ggraph(layout = "linear", circular = TRUE) +
    ggraph(layout = "fr") +
      geom_edge_link(aes(edge_width = r),
                     edge_alpha = 0.3,
                     edge_colour = "cyan4") +
      geom_node_point(aes(colour = name, size=인구/10^4)) +
      geom_node_text(aes(label = name), repel = TRUE) +
      theme_graph(base_family = "NanumGothic")

2 제6회 지방선거

제6회 지방선거는 여전히 지역에 따른 정치색이 살아있는 선거결과였다는 것이 위키, 제6회 전국동시지방선거에서 나타나고 있다.

제7회 지방선거와 마찬가지로 데이터를 가져와서 정제작업을 수행한다.

# 1. 데이터 -----
## 1.1. 제 7 회 지방선거 여론조사 -----
six_url <- "https://ko.wikipedia.org/wiki/제6회_전국동시지방선거"

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


# 2. 데이터 정제 -----
## 2.1. 지방선거 데이터 정제
six_df <- six_dat %>% 
    gather(정당, 득표수, -지역) %>% 
    filter(!str_detect(지역, "전국"),
           !str_detect(정당, "기타|합계")) %>% 
    mutate(득표수 = str_replace_all(득표수, "\\,|\\.", "") %>% as.integer) %>% 
    filter(정당 %in% c("새누리당", "새정치민주연합", "정의당", "통합진보당")) %>% 
    as_tibble()

2.1 상관분석

제7회 지방선거와 동일하게 상관분석작업을 수행한다.

## 2.2. 상관계수 행렬
six_cor_df <- six_df %>% 
    spread(지역, 득표수, fill=0L) %>% 
    as.data.frame() %>% 
    column_to_rownames(var="정당") %>% 
    correlate() %>% 
    rearrange()

six_cor_df %>% 
    as.data.frame() %>% 
    column_to_rownames(var="rowname") %>% 
    replace(., is.na(.), 1) %>% 
    as.matrix() %>% 
    corrplot.mixed(., upper="ellipse")

2.2 네트워크 시각화

제7회 지방선거와 동일하게 네트워크 시각화작업을 수행한다.

## 2.3. 네트워크 그래프
### 2.3.1. 네트워크 그래프 데이터 변환: 상관계수행렬 --> 네트워크 from to 
six_nw_df <- six_cor_df %>% 
    stretch(na.rm = TRUE) %>% 
    arrange(-r)

six_nw <- as_tbl_graph(six_nw_df, directed=FALSE)

### 2.3.1. 네트워크 그래프 데이터 변환
six_nw %>% 
    activate(edges) %>% 
    filter(!edge_is_loop()) %>% 
    activate(nodes) %>% 
    filter(!str_detect(name, "세종")) %>% 
    left_join(pop_df, by=c("name" = "지역")) %>% 
    mutate(community = as.factor(group_infomap(node_weights = 인구, weights = abs(r)))) %>% 
    # ggraph(layout = "linear", circular = TRUE) +
    ggraph(layout = "fr") +
      geom_edge_link(aes(edge_width = r),
                     edge_alpha = 0.3,
                     edge_colour = "cyan4") +
      geom_node_point(aes(colour = community, size=인구/10^4)) +
      geom_node_text(aes(label = name), repel = TRUE) +
      theme_graph(base_family = "NanumGothic")

3 무너진 지역구도

제6회, 제7회 광역의원 비례대표 정당별 득표 데이터를 통해서 그동안 공공히 유지되었던 지역주의가 완화된 것이 상관분석을 통해 확인된다.

par(mfrow=c(1,2))

six_cor_df %>% 
    as.data.frame() %>% 
    column_to_rownames(var="rowname") %>% 
    replace(., is.na(.), 1) %>% 
    as.matrix() %>% 
    corrplot.mixed(., upper="ellipse")

seven_cor_df %>% 
    as.data.frame() %>% 
    column_to_rownames(var="rowname") %>% 
    replace(., is.na(.), 1) %>% 
    as.matrix() %>% 
    corrplot.mixed(., upper="ellipse")