위키백과 대한민국 제7회 지방 선거 여론 조사 웹페이지에서 최신 내용을 확인할 수 있다. 데이터를 분석하는 현재 시점(2018-05-22) 지방선거는 앞으로 22일 남았다.
더불어 민주당으로 기울어진 운동장에서 자유한국당, 바른미래당, 민주평화당, 정의당을 비롯한 각당이 각축을 벌이고 있다. 결국 제6회 지방선거와 제7회 6.13지방선거 후 정계개편 방향에 대해서 파악할 필요가 있다.
이를 위해서 제6회 지방선거 결과와 현재 시점(2018-05-22) 제7회 지방선거 여론조사를 비교하여 약 22일 남은 시점 지지층 결집과 향후 정계지형도를 파악해 보자.
위키백과 제6히 지방선거 웹페이지에서 선거 결과를 받아와서 이를 데이터테이블로 표현한다. 경상북도지사를 3선 연임에 성공한 김관용 경북지사가 눈에 들어온다. 현 국무총리인 이낙연 총리는 78% 득표율로 가장 높은 득표율을 기록했으며, 박원순 서울특별시장이 가장 많은 득표를 했으며, 세종특별자치시장은 36,203표를 득표하고 광역단체장에 당당히 이름을 올렸다.
# 1. 데이터 -----
## 1.1. 제 6 회 지방선거 결과 -----
### 데이터 가져오기
Sys.setlocale("LC_ALL", "C")
six_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"
sido_six_df <- read_html(six_url) %>%
html_node(xpath='//*[@id="mw-content-text"]/div/table[4]') %>%
html_table(fill=TRUE)
Sys.setlocale("LC_ALL", "Korean")
### 데이터 정제
sido_six_df <- sido_six_df %>%
filter(!str_detect(지역, "투표율")) %>%
mutate(득표수 = str_replace_all(득표수, ",", "") %>% as.integer,
득표율 = str_replace_all(득표율, "%", "") %>% as.numeric) %>%
mutate(선수 = ifelse(비고 == "", "초선", 비고)) %>%
mutate(선수 = factor(선수, levels = c("초선", "재선", "3선"))) %>%
rename(시도명=지역)
### 데이터 저장
DT::datatable(sido_six_df)
위키백과 제7회 지방선거 여론조사 웹페이지에서 현재시점 여론조사 결과를 가져온다. 현재시점(2018-05-22) 여론조사결과가 공표되지 않은 곳도 다수 있고, 경쟁이 치열한 일부 시도의 경우 다양한 여론조사기관을 통해 복수의 여론조사 결과도 공표되어 있다.
# 1. 데이터 -----
## 1.1. 제 7 회 지방선거 여론조사 -----
### 데이터 가져오기
seven_url <- "https://ko.wikipedia.org/wiki/대한민국_제7회_지방_선거_여론_조사"
sido_v <- c("서울특별시장","인천광역시장","경기도지사","강원도지사","대전광역시장","세종특별자치시장","충청남도지사","충청북도지사","광주광역시장","전라남도지사","전라북도지사","부산광역시장","대구광역시장","울산광역시장","경상남도지사","경상북도지사","제주특별자치도지사")
crawl_survey <- function(sido_index) {
sido_df <- read_html(seven_url) %>%
html_nodes("table") %>%
.[[sido_index+1]] %>%
html_table(fill=TRUE)
sido_df <- sido_df %>%
mutate_at(vars(contains("당")), funs(str_replace_all(., "%", ""))) %>%
mutate_at(vars(contains("기타")), funs(str_replace_all(., "%", ""))) %>%
mutate_at(vars(contains("응답")), funs(str_replace_all(., "명|,", "")))
sido_df <- sido_df %>% filter(! row_number() %in% c(1)) %>%
separate("조사 기간", into=c("시작일", "종료일"), sep="\\~") %>%
separate(시작일, into=c("월", "일"), sep=" ") %>%
mutate(월 = str_extract(월, "[0-9]+"),
일 = str_extract(일, "[0-9]+")) %>%
mutate(조사일 = ymd(str_c("2018-", 월, "-", 일))) %>%
select(-월, -일, -종료일) %>%
mutate("시도명" = sido_v[sido_index])
return(sido_df)
}
assign(sido_v[1], crawl_survey(1)) # 1.1 서울특별시장
assign(sido_v[2], crawl_survey(2)) # 1.2 인천광역시장
assign(sido_v[3], crawl_survey(3)) # 1.3 경기도지사
assign(sido_v[4], crawl_survey(4)) # 1.4 강원도지사
assign(sido_v[5], crawl_survey(5)) # 1.5 대전광역시장
assign(sido_v[6], crawl_survey(6)) # 1.6 세종특별자치시장
assign(sido_v[7], crawl_survey(7)) # 1.7 충청남도지사
assign(sido_v[8], crawl_survey(8)) # 1.8 충청북도지사
assign(sido_v[9], crawl_survey(9)) # 1.9 광주광역시장
assign(sido_v[10], crawl_survey(10)) # 1.10 전라남도지사
assign(sido_v[11], crawl_survey(11)) # 1.11 전라북도지사
assign(sido_v[12], crawl_survey(12)) # 1.12 부산광역시장
assign(sido_v[13], crawl_survey(13)) # 1.13 대구광역시장
assign(sido_v[14], crawl_survey(14)) # 1.14 울산광역시장
assign(sido_v[15], crawl_survey(15)) # 1.15 경상남도지사
assign(sido_v[16], crawl_survey(16)) # 1.16 경상북도지사
assign(sido_v[17], crawl_survey(17)) # 1.17 제주특별자치도지사
sido_list <- mget(sido_v)
sido_survey_df <- map_df(sido_list, bind_rows)
DT::datatable(sido_seven_df)
Slopegraph를 통해서 제6회 지방선거와 제7회 지방선거 전후변화를 시각적으로 표현하는데 적절할 것으로 판단된다. 이를 위해서 Edward Tufte’s Slopegraphs and political fortunes in Ontario의 코드를 참조해서 정계개편 전후를 비교하여 시각화한다.
bumpchart2<-function (y, top.labels = colnames(y), labels = rep(rownames(y),2),
rank = TRUE, mar = c(2, 8, 5, 8), pch = 19, col = par("fg"),
lty = 1, lwd = 1, arrows = FALSE, ...) {
if (missing(y)) stop("Usage: bumpchart(y,top.labels,labels,...)")
ydim <- dim(y)
if (is.null(ydim)) stop("y must be a matrix or data frame")
oldmar <- par("mar")
par(mar = mar)
if (rank)
y <- apply(y, 2, rank)
labels <- rev(labels)
pch = rev(pch)
col = rev(col)
lty = rev(lty)
lwd = rev(lwd)
y <- apply(y, 2, rev)
if (arrows) {
matplot(t(y), ylab = "", type = "p", pch = pch, col = col,
axes = FALSE)
for (row in 1:(ydim[2] - 1)) p2p_arrows(rep(row, ydim[1]),
y[, row], rep(row + 1, ydim[1]), y[, row + 1], col = col,
lty = lty, lwd = lwd, ...)
}
else matplot(t(y), ylab = "", type = "b", pch = pch, col = col,
lty = lty, lwd = lwd, axes = FALSE, ...)
par(xpd = TRUE)
xylim <- par("usr")
minspacing <- strheight("M") * 1.5
text(1:ydim[2], xylim[4], top.labels)
text(xylim[1], y[,1], labels[(ydim[1]+1):(2*ydim[1])], adj = 1)
cat(y[,1],"\n")
text(xylim[2], y[,2], labels[1:ydim[1]], adj = 0)
cat(y[,2],"\n")
par(mar = oldmar, xpd = FALSE)
}
# 1. 데이터 -----
## 1.1. 제6회
sido_six_df <- read_rds("data/sido_six_df.rds")
sido_six_viz_df <- sido_six_df %>%
count(정당)
## 1.2. 제7회 여론조사
sido_seven_df <- read_rds("data/sido_survey_df.rds")
names(sido_seven_df) <- c("조사 의뢰", "조사 기관", "응답 인원", "더불어민주당", "자유한국당", "바른미래당", "정의당", "기타·무응답", "참고", "조사일", "시도명", "민주평화당", "무소속")
sido_seven_now_df <- sido_seven_df %>%
mutate(무소속 = str_replace_all(무소속, "%", "") %>% as.numeric,
민주평화당 = str_replace_all(민주평화당, "%", "") %>% as.numeric) %>%
group_by(시도명) %>%
filter(조사일 == max(조사일)) %>%
select(시도명, contains("당"), contains("무소속")) %>%
ungroup()
current_df <- sido_seven_now_df %>%
gather(정당, 지지율, -시도명) %>%
mutate(지지율 = as.numeric(지지율)) %>%
group_by(시도명) %>%
summarise(지지율 = max(지지율, na.rm=TRUE))
sido_current_df <- sido_seven_now_df %>%
gather(정당, 지지율, -시도명) %>%
mutate(지지율 = as.numeric(지지율)) %>%
inner_join(current_df)
sido_seven_viz_df <- sido_current_df %>%
count(정당)
# 2. 시각화 -----
sido_six_viz_df <- sido_six_viz_df %>%
mutate(정당 = case_when(str_detect(정당, "새누리당") ~ "자유한국당",
str_detect(정당, "새정치민주연합") ~ "더불어민주당")) %>%
rename(제6회 = n)
sido_seven_viz_df <- sido_seven_viz_df %>%
rename(제7회 = n)
sido_viz_df <- full_join(sido_six_viz_df, sido_seven_viz_df) %>%
mutate(제6회 = ifelse(is.na(제6회), 0, 제6회) %>% as.integer) %>%
as.data.frame() %>%
column_to_rownames("정당")
bumpchart2(sido_viz_df, mar=c(6, 12, 6, 12),col=c("red", "blue", "darkgray"),
labels=c(paste(rownames(sido_viz_df),sido_viz_df[,1],sep=" "),
paste(sido_viz_df[,2],rownames(sido_viz_df),sep=" ")),rank=FALSE,lwd=3,
top.labels = c("제6회", "제7회"))
0 9 8
1 8 1
title(main="지방선거 전후 정계 개편", line=1.5, col.main="navy blue")
title(sub="https://ko.wikipedia.org/wiki/대한민국_제6회_지방_선거\nhttps://ko.wikipedia.org/wiki/대한민국_제7회_지방_선거",
line=2, cex.sub =.8, col.sub="blue")
지방선거 전후 정치지형변화를 공간정보로 지도위에 표현해 보자. 물론, 충청북도, 대전, 세종, 광주, 전라남북 등 여론조사가 공표되고 있지않아 공란으로 남아있지만, 조만간 여론조사가 공포되면 지방선거 판세예측과 더불어 정계개편 방향을 한눈에 파악하는데 유용할 것으로 생각됩니다.
# 1. 데이터 -----
# 1.0. 지도정보 룩업표
spatial_tbl <- tribble(
~"CTPRVN_CD", ~"CTP_KOR_NM", ~"시도명",
11, "서울특별시", "서울특별시장",
26, "부산광역시", "부산광역시장",
27, "대구광역시", "대구광역시장",
28, "인천광역시", "인천광역시장",
29, "광주광역시", "광주광역시장",
30, "대전광역시", "대전광역시장",
31, "울산광역시", "울산광역시장",
36, "세종특별자치시", "세종특별자치시장",
41, "경기도", "경기도지사",
42, "강원도", "강원도지사",
43, "충청북도", "충청북도지사",
44, "충청남도", "충청남도지사",
45, "전라북도", "전라북도지사",
46, "전라남도", "전라남도지사",
47, "경상북도", "경상북도지사",
48, "경상남도", "경상남도지사",
50, "제주특별자치도", "제주특별자치도지사"
)
## 1.1. 제6회 지방선거
sido_six_df <- left_join(sido_six_df, spatial_tbl) %>%
mutate(CTPRVN_CD = factor(CTPRVN_CD))
## 1.2. 제7회 여론조사
sido_seven_now_df <- sido_seven_df %>%
mutate(무소속 = str_replace_all(무소속, "%", "") %>% as.numeric,
민주평화당 = str_replace_all(민주평화당, "%", "") %>% as.numeric) %>%
group_by(시도명) %>%
filter(조사일 == max(조사일)) %>%
select(시도명, contains("당"), contains("무소속")) %>%
ungroup()
current_df <- sido_seven_now_df %>%
gather(정당, 지지율, -시도명) %>%
mutate(지지율 = as.numeric(지지율)) %>%
group_by(시도명) %>%
summarise(지지율 = max(지지율, na.rm=TRUE))
sido_current_df <- sido_seven_now_df %>%
gather(정당, 지지율, -시도명) %>%
mutate(지지율 = as.numeric(지지율)) %>%
inner_join(current_df)
## 1.3. 지방선거 지도 -----
## 1.2. shp 파일 불러오기 --------
# sido_shp <- st_read("data/shapefile_sido/TL_SCCO_CTPRVN.shp")
# sido_shp <- st_read("data/TL_SCCO_CTPRVN.shp")
sido_shp$CTP_KOR_NM <- iconv(sido_shp$CTP_KOR_NM, from = "CP949", to = "UTF-8", sub = NA, mark = TRUE, toRaw = FALSE)
sido_simp_shp <- st_simplify(sido_shp, dTolerance = 100)
# 2. 시각화 -----
## 2.1. 제6회 지방선거
sido_six_shp <- left_join(sido_simp_shp, sido_six_df)
sido_six_g <- sido_six_shp %>% ggplot(aes(fill=sido_six_shp$정당)) +
geom_sf() +
theme_minimal(base_family="NanumGothic") +
labs(title="제6회 지방선거 - 광역자치단체장") +
theme(legend.position = "right") +
scale_fill_manual(values =c("red", "blue")) +
labs(fill="정당") +
theme(legend.position = "top")
## 2.2. 제7회 지방선거
sido_current_df <- left_join(sido_current_df, spatial_tbl) %>%
mutate(CTPRVN_CD = factor(CTPRVN_CD))
sido_seven_shp <- left_join(sido_simp_shp, sido_current_df)
sido_seven_g <- sido_seven_shp %>% ggplot(aes(fill=sido_seven_shp$정당)) +
geom_sf() +
theme_minimal(base_family="NanumGothic") +
labs(title="제7회 지방선거 - 광역자치단체장") +
theme(legend.position = "right") +
scale_fill_manual(values =c("blue", "darkgray", "red")) +
labs(fill="정당") +
theme(legend.position = "top")
## 2.3. 제6회, 제7회 지방선거 비교
grid.arrange(sido_six_g, sido_seven_g, nrow=1)