중앙선거관리위원회 웹사이트에서 시도 데이터를 받아보자.
library(tidyverse)
library(rvest)
library(httr)
<- "http://info.nec.go.kr/electioninfo/electionInfo_report.xhtml?electionId=0020220309&requestURI=%2FWEB-INF%2Fjsp%2Felectioninfo%2F0020220309%2Fvc%2Fvccp09.jsp&topMenuId=VC&secondMenuId=VCCP09&menuId=VCCP09&statementId=VCCP09_%231&electionCode=1&cityCode=0&sggCityCode=0&townCode=-1&sggTownCode=0&x=94&y=25"
nec_20_url
<- read_html(nec_20_url)
nec_20_html
Sys.setlocale("LC_ALL", "C")
[1] "C"
<- nec_20_html %>%
nec_20_raw html_elements(css = '.table01') %>%
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"
<- nec_20_raw %>%
nec_20_tbl ::clean_names(ascii = FALSE) %>%
janitorset_names(c("시도명", "선거인수", "투표수", "이재명", "윤석열", "심상정", "오준호", "허경영", "이백윤", "옥은호", "김경재", "조원진", "김재연", "이경희", "김민찬", "계", "무효투표수", "기권수", "개표율")) %>%
slice(2:n()) %>%
filter(시도명 != "") %>%
pivot_longer(이재명:김민찬, names_to = "후보", values_to = "득표수") %>%
mutate(득표수 = parse_number(득표수)) %>%
select(시도명, 후보, 득표수) %>%
filter(시도명 != "합계")
nec_20_tbl
# A tibble: 204 x 3
시도명 후보 득표수
<chr> <chr> <dbl>
1 서울특별시 이재명 2944981
2 서울특별시 윤석열 3255747
3 서울특별시 심상정 180324
4 서울특별시 오준호 3829
5 서울특별시 허경영 36540
6 서울특별시 이백윤 1571
7 서울특별시 옥은호 844
8 서울특별시 김경재 1791
9 서울특별시 조원진 4657
10 서울특별시 김재연 5615
# ... with 194 more rows
<- nec_20_tbl %>%
nec_20_viz group_by(시도명) %>%
mutate(득표율 = 득표수 / sum(득표수) ) %>%
ungroup() %>%
filter(후보 %in% c("이재명", "윤석열")) %>%
## 시각화를 위한 차이
select(-득표수) %>%
pivot_wider(names_from = 후보, values_from = 득표율) %>%
mutate(차이 = 이재명 - 윤석열)
nec_20_viz
# A tibble: 17 x 4
시도명 이재명 윤석열 차이
<chr> <dbl> <dbl> <dbl>
1 서울특별시 0.457 0.506 -0.0483
2 부산광역시 0.382 0.583 -0.201
3 대구광역시 0.216 0.751 -0.535
4 인천광역시 0.489 0.471 0.0186
5 광주광역시 0.848 0.127 0.721
6 대전광역시 0.464 0.496 -0.0311
7 울산광역시 0.408 0.544 -0.136
8 세종특별자치시 0.519 0.441 0.0777
9 경기도 0.509 0.456 0.0532
10 강원도 0.417 0.542 -0.125
11 충청북도 0.451 0.507 -0.0555
12 충청남도 0.450 0.511 -0.0612
13 전라북도 0.830 0.144 0.686
14 전라남도 0.861 0.114 0.747
15 경상북도 0.238 0.728 -0.490
16 경상남도 0.374 0.582 -0.209
17 제주특별자치도 0.526 0.427 0.0990
library(sf)
<- st_read("data/tilemap_sido/sido_hex_map_raw.shp") sido_tilemap
Reading layer `sido_hex_map_raw' from data source
`C:\docs\president\data\tilemap_sido\sido_hex_map_raw.shp'
using driver `ESRI Shapefile'
Simple feature collection with 17 features and 2 fields
Geometry type: POLYGON
Dimension: XY
Bounding box: xmin: 847131 ymin: 1576357 xmax: 1189641 ymax: 2045920
Projected CRS: PCS_ITRF2000_TM
%>%
sido_tilemap ggplot() +
geom_sf(aes(geometry = geometry)) +
theme_void()
<- sido_tilemap %>%
sido_tilemap_sf left_join(nec_20_viz, by = c("CTP_KOR_NM" = "시도명")) %>%
left_join(nesdc::sido_code, by = c("CTP_KOR_NM" = "시도명") ) %>%
mutate(label = glue::glue("{시도}\n{scales::percent(차이, accuracy =0.1)}"))
sido_tilemap_sf
Simple feature collection with 17 features and 8 fields
Geometry type: POLYGON
Dimension: XY
Bounding box: xmin: 847131 ymin: 1576357 xmax: 1189641 ymax: 2045920
Projected CRS: PCS_ITRF2000_TM
First 10 features:
CTPRVN_CD CTP_KOR_NM 이재명 윤석열 차이 시도코드 시도
1 29 광주광역시 0.8482088 0.1272337 0.72097515 2900 광주
2 46 전라남도 0.8610084 0.1144599 0.74654849 4600 전남
3 48 경상남도 0.3738236 0.5824603 -0.20863664 4800 경남
4 26 부산광역시 0.3815725 0.5825543 -0.20098175 2600 부산
5 45 전라북도 0.8298084 0.1442845 0.68552389 4500 전북
6 30 대전광역시 0.4644912 0.4955783 -0.03108711 3000 대전
7 27 대구광역시 0.2160845 0.7514300 -0.53534556 2700 대구
8 44 충청남도 0.4496495 0.5108424 -0.06119290 4400 충남
9 36 세종특별자치시 0.5191547 0.4414744 0.07768029 5100 세종
10 43 충청북도 0.4512462 0.5067476 -0.05550139 4300 충북
geometry label
1 POLYGON ((864318.2 1740704,... 광주\n72.1%
2 POLYGON ((945649 1740704, 9... 전남\n74.7%
3 POLYGON ((1026980 1740704, ... 경남\n-20.9%
4 POLYGON ((1108310 1740704, ... 부산\n-20.1%
5 POLYGON ((904983.6 1811138,... 전북\n68.6%
6 POLYGON ((986314.3 1811138,... 대전\n-3.1%
7 POLYGON ((1067645 1811138, ... 대구\n-53.5%
8 POLYGON ((864318.2 1881573,... 충남\n-6.1%
9 POLYGON ((945649 1881573, 9... 세종\n7.8%
10 POLYGON ((1026980 1881573, ... 충북\n-5.6%
<- sido_tilemap_sf %>%
sido_tilemap_g ggplot() +
geom_sf(aes(geometry = geometry, fill = 차이)) +
theme_void(base_family = "NanumBarunpen") +
geom_sf_text(aes(geometry = geometry, label = label),
size = 7,
fun.geometry = function(x) st_centroid(x)) +
scale_fill_gradientn( colours = c("red", "white", "blue"), labels = scales::percent) +
labs(
title = "제20대 대통령선거 시도별 득표율 차이",
subtitle = "득표율 차이: |이재명(47.83%) - 윤석열(48.56%)| = 0.73%",
fill = "득표율 차이(%)",
caption = "데이터출처: 중앙선거관리위원회 선거통계시스템"
+
) theme(
text = element_text(family = "NanumBarunpen"),
plot.tag.position = c(0.85, .97),
legend.position = "right",
legend.title=element_text(size=15),
legend.key.size = unit(1.5, 'cm'),
legend.text=element_text(size=13),
plot.title=element_text(size=25, face="bold", family = "NanumBarunpen"),
plot.subtitle=element_text(face="bold", size=17, colour="grey10", family = "NanumBarunpen"))
sido_tilemap_g
::agg_png("fig/sido_tilemap_g.png", width = 297, height = 210, units = "mm", res = 600, scaling = 0.85)
ragg
sido_tilemap_gdev.off()
png
2
데이터 과학자 이광춘 저작
kwangchun.lee.7@gmail.com