수도권 국힘의원

수도권 국민의힘 의원

저자
소속

1 데이터셋

1.1 서울특별시

코드
library(tidyverse)

elected_tbl <- 
  read_rds("data/total_elected_all.rds")

seoul_tbl <- elected_tbl |> 
  filter(sgId %in% c("20160413", "20200415", "20120411", "20080409", "20040415")) |> 
  filter(str_detect(sdName, "서울")) |>
  select(result) |> 
  unnest(result) |> 
  mutate(정당명 = case_when(
    jdName %in% c("한나라당", "새누리당", "미래통합당") ~ "국민의힘",
    jdName %in% c("더불어민주당", "열린우리당", "통합민주당", "민주통합당") ~ "민주당",                 TRUE ~ "기타")) |> 
  count(sgId, 정당명) |> 
  pivot_wider(names_from = 정당명, values_from = n, values_fill = 0) |> 
  mutate(합계 = 국민의힘 + 민주당 + 기타)

1.2 경기도

코드
gg_tbl <- elected_tbl |> 
  filter(sgId %in% c("20160413", "20200415", "20120411", "20080409", "20040415")) |> 
  filter(str_detect(sdName, "경기")) |>
  select(result) |> 
  unnest(result) |> 
  mutate(정당명 = case_when(
    jdName %in% c("한나라당", "새누리당", "미래통합당") ~ "국민의힘",
    jdName %in% c("더불어민주당", "열린우리당", "통합민주당", "민주통합당") ~ "민주당",                 TRUE ~ "기타")) |> 
  count(sgId, 정당명) |> 
  pivot_wider(names_from = 정당명, values_from = n, values_fill = 0) |> 
  mutate(합계 = 국민의힘 + 민주당 + 기타)

2 분석

2.1 서울특별시

코드
library(gt)
library(gtExtras)

seoul_tbl |> 
  gt(rowname_col = "sgId") |> 
  gt_theme_538() |> 
  cols_align("center") |> 
  cols_label(
    sgId = "선거명"
  ) |> 
  ## 표 전체 합계 -------------------------------------
  grand_summary_rows(
    columns = c(국민의힘, 민주당, 기타, 합계),
    fns =  list(label = "총계", fn = "sum"),
    fmt = ~ fmt_integer(.),
    side = "top"
  )  |> 
  tab_header(
    title = md("서울특별시 국회의원 역대 당선자 현황"),
    subtitle = md("중앙선거관리위원회 선거통계")
  ) |> 
  tab_spanner(
    label = "정당명",
    columns = c(
      국민의힘, 민주당, 기타
    )
  )  |> 
  tab_style(
    style = cell_text(align = "center"),
    locations = cells_stub_grand_summary()
  )  
서울특별시 국회의원 역대 당선자 현황
중앙선거관리위원회 선거통계
정당명 합계
국민의힘 민주당 기타
총계 92 145 5 242
20040415 16 32 0 48
20080409 40 7 1 48
20120411 16 30 2 48
20160413 12 35 2 49
20200415 8 41 0 49

2.2 경기도

코드
gg_tbl |> 
  gt(rowname_col = "sgId") |> 
  gt_theme_538() |> 
  cols_align("center") |> 
  cols_label(
    sgId = "선거명"
  ) |> 
  ## 표 전체 합계 -------------------------------------
  grand_summary_rows(
    columns = c(국민의힘, 민주당, 기타, 합계),
    fns =  list(label = "총계", fn = "sum"),
    fmt = ~ fmt_integer(.),
    side = "top"
  )  |> 
  tab_header(
    title = md("경기도 국회의원 역대 당선자 현황"),
    subtitle = md("중앙선거관리위원회 선거통계")
  ) |> 
  tab_spanner(
    label = "정당명",
    columns = c(
      국민의힘, 민주당, 기타
    )
  )  |> 
  tab_style(
    style = cell_text(align = "center"),
    locations = cells_stub_grand_summary()
  )  
경기도 국회의원 역대 당선자 현황
중앙선거관리위원회 선거통계
정당명 합계
국민의힘 민주당 기타
총계 93 172 6 271
20040415 14 35 0 49
20080409 32 17 2 51
20120411 21 29 2 52
20160413 19 40 1 60
20200415 7 51 1 59

3 지도

3.1 서울특별시

코드
library(sf)

precinct <- st_read("data/2020_21_elec_253.json") |> 
  st_set_crs(4326)
#> Reading layer `2020_21_elec_253' from data source 
#>   `D:\tcs\map_challenge\data\2020_21_elec_253.json' using driver `GeoJSON'
#> Simple feature collection with 253 features and 4 fields
#> Geometry type: MULTIPOLYGON
#> Dimension:     XY
#> Bounding box:  xmin: 124.6097 ymin: 33.11187 xmax: 131.8713 ymax: 38.61695
#> Geodetic CRS:  WGS 84

seoul_precinct <- precinct |> 
  filter(SGG_1 == "서울") 

st_geometry(seoul_precinct) |> plot()

코드
seoul_party_tbl <- elected_tbl |> 
  filter(sgId %in% c("20200415")) |> 
  filter(str_detect(sdName, "서울")) |>
  select(result) |> 
  unnest(result) |> 
  mutate(정당명 = case_when(
    jdName %in% c("한나라당", "새누리당", "미래통합당") ~ "국민의힘",
    jdName %in% c("더불어민주당", "열린우리당", "통합민주당", "민주통합당") ~ "민주당",                 TRUE ~ "기타")) |> 
  select(sggName, wiwName, giho, jdName, name, dugsu, dugyul, 정당명)

seoul_precinct_party <- seoul_precinct |> 
  mutate(sggName = str_remove(SGG_2, "서울특별시 ")) |> 
  left_join(seoul_party_tbl)
코드
seoul_precinct_party |> 
  mutate(정당명 = case_when(
    jdName %in% c("한나라당", "새누리당", "미래통합당") ~ "국민의힘",
    jdName %in% c("더불어민주당", "열린우리당", "통합민주당", "민주통합당") ~ "민주당",
    jdName %in% c("정의당") ~ "정의당",
    TRUE ~ "기타")) |>   
  ggplot() +
    geom_sf(aes(geometry = geometry, fill = 정당명), alpha =0.2) +
    scale_fill_manual(values = c("민주당" = "blue",
                                  "국민의힘" = "red",
                                  "정의당" = "yellow")) +
    theme_void() +
    theme(legend.position = "top") +
    labs(fill = "정당명") +
    ggrepel::geom_text_repel(
        aes(label = sggName, geometry = geometry,
            color = 정당명), stat = "sf_coordinates", 
        min.segment.length = 1, size = 4, max.overlaps = Inf,
        show.legend = FALSE, fontface="bold"
    ) +
    scale_color_manual(values = c("민주당" = "blue",
                                  "국민의힘" = "red",
                                  "정의당" = "black"))

3.2 경기도

코드
gg_precinct <- precinct |> 
  filter(SGG_1 == "경기") 

st_geometry(gg_precinct) |> plot()

코드
gg_party_tbl <- elected_tbl |> 
  filter(sgId %in% c("20200415")) |> 
  filter(str_detect(sdName, "경기")) |>
  select(result) |> 
  unnest(result) |> 
  mutate(정당명 = case_when(
    jdName %in% c("한나라당", "새누리당", "미래통합당") ~ "국민의힘",
    jdName %in% c("더불어민주당", "열린우리당", "통합민주당", "민주통합당") ~ "민주당",                 TRUE ~ "기타")) |> 
  select(sggName, wiwName, giho, jdName, name, dugsu, dugyul, 정당명)

gg_precinct_party <- gg_precinct |> 
  mutate(sggName = str_remove(SGG_2, "경기도 ")) |> 
  left_join(gg_party_tbl)
코드
sf_use_s2(FALSE)
gg_precinct_party |> 
  mutate(정당명 = case_when(
    jdName %in% c("한나라당", "새누리당", "미래통합당") ~ "국민의힘",
    jdName %in% c("더불어민주당", "열린우리당", "통합민주당", "민주통합당") ~ "민주당",
    jdName %in% c("정의당") ~ "정의당",
    TRUE ~ "기타")) |>   
  ggplot() +
    geom_sf(aes(geometry = geometry, fill = 정당명), alpha =0.2) +
    scale_fill_manual(values = c("민주당" = "blue",
                                  "국민의힘" = "red",
                                  "정의당" = "yellow")) +
    theme_void() +
    theme(legend.position = "top") +
    labs(fill = "정당명") +
    ggrepel::geom_text_repel(
        aes(label = sggName, geometry = geometry,
            color = 정당명), stat = "sf_coordinates", 
        min.segment.length = 1, size = 3, max.overlaps = Inf,
        show.legend = FALSE, fontface="bold"
    ) +
    scale_color_manual(values = c("민주당" = "blue",
                                  "국민의힘" = "red",
                                  "정의당" = "black"))

4 득표차

코드
seoul_krvote <- krvote::general_2020 |> 
  filter(시도 == "서울") |> 
  unnest(data) |> 
  mutate(구분 = ifelse(stringi::stri_enc_isutf8(구분), 구분,
                     iconv(구분, from = "euc-kr", to = "utf-8"))) 

seoul_krvote_tbl <- seoul_krvote |> 
  group_by(선거구, 구분) |> 
  summarise(사람수 = sum(사람수)) |> 
  ungroup() |> 
  mutate(정당 = case_when(
    str_detect(구분, "김성식") ~ "국민의힘",
    str_detect(구분, "더불어민주당") ~ "민주당",
    str_detect(구분, "미래통합당") ~ "국민의힘",
    str_detect(구분, "선거인수") ~ "선거인수",
    str_detect(구분, "투표수") ~ "투표수",
    구분 == "계" ~ "계",
    TRUE ~ "기타")) |>  
  filter(정당 %in% c("민주당", "국민의힘", "계")) |> 
  select(선거구, 정당, 사람수) |> 
  pivot_wider(names_from = 정당, values_from = 사람수) |> 
  mutate(민주_득표율 = 민주당 / ,
         국민_득표율 = 국민의힘 / ) |> 
  mutate(득표차 = 민주_득표율 - 국민_득표율) |> 
  mutate(선거구 = ifelse(str_detect(선거구, "_"), 
                      str_extract(선거구, "(.*?)_") |> str_remove("_"), 선거구))
  
seoul_krvote_tbl |> 
  write_rds("data/seoul_krvote_tbl.rds")
코드
seoul_krvote_tbl <- 
  read_rds("data/seoul_krvote_tbl.rds")

seoul_diff_sf <- seoul_precinct_party |> 
  left_join(seoul_krvote_tbl, by = c("sggName" = "선거구")) 

seoul_diff_sf |> 
  ggplot() +
    geom_sf(aes(geometry = geometry, fill = 득표차, color = 정당명), lwd  = 1) +
    scale_fill_gradient2(high = "blue", mid = "gray100", low = "red") +
    theme_void() +
    theme(legend.position = "top") +
    labs(fill = "득표차") +
    ggrepel::geom_text_repel(
        aes(label = str_glue("{sggName}\n{scales::percent(득표차, accuracy=0.1)}"), geometry = geometry), 
        stat = "sf_coordinates", 
        min.segment.length = 0, size = 4, max.overlaps = Inf,
        show.legend = FALSE, fontface="bold", color = "black"
    ) +
    scale_color_manual(values = c("민주당" = "blue",
                                  "국민의힘" = "red"))  

5 강서구

5.1 선거구

코드
library(rvest)

gs_precinct_raw <- read_html("https://ko.wikipedia.org/wiki/서울특별시의_선거구") |> 
  html_elements("table") |> 
  html_table() %>% 
  .[[1]] |> 
  janitor::clean_names(ascii = FALSE) |> 
  filter(str_detect(선거구명, "강서구"))

gs_precinct <- gs_precinct_raw |> 
  mutate(동명 = str_split(관할_구역, ",")) |> 
  select(-관할_구역) |> 
  unnest(동명) |> 
  mutate(동명 = str_remove(동명, "강서구") |> str_squish()) |> 
  mutate(선거구명 = str_remove(선거구명, "\\s+")) |> 
  select(-번호)

gs_precinct
#> # A tibble: 20 × 2
#>    선거구명 동명    
#>    <chr>    <chr>   
#>  1 강서구갑 발산1동 
#>  2 강서구갑 우장산동
#>  3 강서구갑 화곡1동 
#>  4 강서구갑 화곡2동 
#>  5 강서구갑 화곡3동 
#>  6 강서구갑 화곡8동 
#>  7 강서구을 등촌3동 
#>  8 강서구을 가양1동 
#>  9 강서구을 가양2동 
#> 10 강서구을 방화1동 
#> 11 강서구을 방화2동 
#> 12 강서구을 방화3동 
#> 13 강서구을 공항동  
#> 14 강서구병 염창동  
#> 15 강서구병 등촌1동 
#> 16 강서구병 등촌2동 
#> 17 강서구병 가양3동 
#> 18 강서구병 화곡본동
#> 19 강서구병 화곡4동 
#> 20 강서구병 화곡6동
코드
seoul_diff_sf |> 
  filter( str_detect(sggName, "^강서")) |> 
  ggplot() +
    geom_sf(aes(geometry = geometry, fill = 득표차, color = 정당명), lwd  = 1) +
    scale_fill_gradient2(high = "blue", mid = "gray100", low = "red") +
    theme_void() +
    theme(legend.position = "top") +
    labs(fill = "득표차") +
    geom_text(
        aes(label = str_glue("{sggName}\n{scales::percent(득표차, accuracy=0.1)}"), geometry = geometry), 
        stat = "sf_coordinates", 
        show.legend = FALSE, fontface="bold", color = "black"
    ) +
    scale_color_manual(values = c("민주당" = "blue",
                                  "국민의힘" = "red"))  

5.2 행정동 지도

코드
library(sf)

korea_sf <- st_read("data/HangJeongDong_ver20230701.geojson")
#> Reading layer `123' from data source 
#>   `D:\tcs\map_challenge\data\HangJeongDong_ver20230701.geojson' 
#>   using driver `GeoJSON'
#> Simple feature collection with 3523 features and 9 fields
#> Geometry type: MULTIPOLYGON
#> Dimension:     XY
#> Bounding box:  xmin: 124.6097 ymin: 33.11187 xmax: 131.8713 ymax: 38.61695
#> Geodetic CRS:  WGS 84

gs_sf <- korea_sf |> 
  filter(sidonm == "서울특별시",
         sggnm  == "강서구") |> 
  mutate(dongnm = str_remove(adm_nm, "서울특별시 강서구 ")) |> 
  select(sidonm, sggnm, dongnm, geometry) |> 
  left_join(gs_precinct, by = c("dongnm" = "동명"))

gs_precinct_sf <- gs_sf |> 
  group_by(선거구명) |> 
  summarise(geometry = st_union(geometry))

gs_precinct_centroid <- st_centroid(gs_precinct_sf)

ggplot() +
  geom_sf(data = gs_sf, aes(fill = dongnm), alpha = 0.3, show.legend = FALSE) +
  geom_sf(data = gs_precinct_sf, color = "gray30",
          alpha = 0.0, lwd = 1, show.legend = FALSE) +
  theme_void() +
  geom_sf(data = gs_precinct_centroid, color = "black") +
  ggrepel::geom_text_repel(data = gs_precinct_centroid, 
                           aes(label = 선거구명, geometry = geometry), stat = "sf_coordinates", 
        min.segment.length = 1, size = 4, max.overlaps = Inf)

5.3 재보궐 선거

코드
library(ggrepel)

gs_raw <- readxl::read_excel("data/[2023년_하반기_재·보궐선거]_개표단위별_개표결과.xlsx",
                   sheet = "Sheet1", skip =4)

gs_tbl <- gs_raw |> 
  set_names(c("읍면동명", "투표구명", "선거인수", "투표수", "민주당", 
"국민의힘", "정의당", "x11", "진보당", 
"녹색당", "자유통일당", "계", 
"무표투표수", "기권수")) |>
  select(-x11) |> 
  mutate(읍면동명 = str_replace(읍면동명, "제(\\d+)", "\\1")) |> 
  filter(투표구명 == "소계") |> 
  mutate(across(선거인수:기권수, parse_number)) |> 
  mutate(투표율 = 투표수 / 선거인수)  |> 
  left_join(gs_precinct, by = c("읍면동명"="동명"))

gs_tbl |>
  group_by(선거구명, 읍면동명) |> 
  summarise(선거인수 = sum(선거인수),
            투표수 = sum(투표수)) |> 
  mutate(투표율 = 투표수 / 선거인수) |> 
  ggplot(aes(x = fct_reorder(읍면동명, 투표율), y = 투표율, fill = 선거구명)) +
    geom_col( width = 0.5 ) +
    facet_wrap(vars(선거구명), scales = "free") +
    labs(x = "") +
    theme_minimal() +
    scale_y_continuous(labels = scales::percent) +
    theme(legend.position = "none")

코드
    
gs_tbl |>   
  mutate(민주_득표율 = 민주당 / ,
         국힘_득표율 = 국민의힘 / ) |> 
  mutate(득표차 = 민주_득표율 - 국힘_득표율) |> 
  ggplot(aes(x = fct_reorder(읍면동명, 득표차), y = 득표차, fill = 선거구명)) +
    geom_col( width = 0.5 ) +
    facet_wrap(vars(선거구명), scales = "free") +
    labs(x = "") +
    theme_minimal() +
    scale_y_continuous(labels = scales::percent) +
    theme(legend.position = "none")

5.4 투표율과 득표차

코드
gs_tbl |>   
  mutate(민주_득표율 = 민주당 / ,
         국힘_득표율 = 국민의힘 / ) |> 
  mutate(득표차 = 민주_득표율 - 국힘_득표율) |> 
  mutate(투표율 = 투표수 / 선거인수) |> 
  select(선거구명, 선거인수, 읍면동명, 득표차, 투표율) |> 
  ggplot(aes(x = 투표율, y = 득표차, color = 선거구명)) +
    geom_point(aes(size = 선거인수)) +
    facet_wrap(vars(선거구명)) +
    geom_text_repel(aes(label = 읍면동명)) +
    theme_minimal() +
    theme(legend.position = "top") +
    scale_x_continuous(labels = scales::percent) +
    scale_y_continuous(labels = scales::percent) +
    labs(x = "투표율", y = "득표차",
         title = "강서구 재보궐선거 투표율과 득표차",
         subtitle = "득표차 = 민주당 후보 득표율 - 국힘 후보 득표율 ") +
    guides(color = FALSE) +
    scale_size_continuous(labels = scales::comma)

6 2020 선거

코드
## 강서갑
gs_gap_raw <- readxl::read_excel("data/2020_강서구_개표현황_읍면동별.xlsx",
                   sheet = "강서구갑", skip =4)

gs_gap <- gs_gap_raw |> 
  set_names(c("선거구명", "읍면동명", "구분", "선거인수", "투표수", "민주당", 
"국민의힘", "x11", "민중당", "국가혁명당", "무소속", "계", 
"무표투표수", "기권수")) |>
  select(-x11) |> 
  fill(선거구명, .direction = "down") |> 
  mutate(읍면동명 = str_replace(읍면동명, "제(\\d+)", "\\1")) |> 
  filter(구분 == "계") |> 
  mutate(across(선거인수:기권수, parse_number)) |> 
  mutate(투표율 = 투표수 / 선거인수)  

## 강서을
gs_eul_raw <- readxl::read_excel("data/2020_강서구_개표현황_읍면동별.xlsx",
                   sheet = "강서구을", skip =4)

gs_eul <- gs_eul_raw |> 
  set_names(c("선거구명", "읍면동명", "구분", "선거인수", "투표수", "민주당", 
"국민의힘", "x11", "우리공화당", "국가혁명당", "무소속", "계", 
"무표투표수", "기권수")) |>
  select(-x11) |> 
  fill(선거구명, .direction = "down") |> 
  mutate(읍면동명 = str_replace(읍면동명, "제(\\d+)", "\\1")) |> 
  filter(구분 == "계") |> 
  mutate(across(선거인수:기권수, parse_number)) |> 
  mutate(투표율 = 투표수 / 선거인수)  

## 강서병
gs_byung_raw <- readxl::read_excel("data/2020_강서구_개표현황_읍면동별.xlsx",
                   sheet = "강서구병", skip =4)

gs_byung <- gs_byung_raw |> 
  set_names(c("선거구명", "읍면동명", "구분", "선거인수", "투표수", "민주당", 
"국민의힘", "x11", "민중당", "국가혁명당", "무소속", "계", 
"무표투표수", "기권수")) |>
  select(-x11) |> 
  fill(선거구명, .direction = "down") |> 
  mutate(읍면동명 = str_replace(읍면동명, "제(\\d+)", "\\1")) |> 
  filter(구분 == "계") |> 
  mutate(across(선거인수:기권수, parse_number)) |> 
  mutate(투표율 = 투표수 / 선거인수)  

## 강서구

gs_old <- bind_rows(gs_gap, gs_eul) |> 
  bind_rows(gs_byung)

6.1 시각화

코드
gs_old |>
  group_by(선거구명, 읍면동명) |> 
  summarise(선거인수 = sum(선거인수),
            투표수 = sum(투표수)) |> 
  mutate(투표율 = 투표수 / 선거인수) |> 
  ggplot(aes(x = fct_reorder(읍면동명, 투표율), y = 투표율, fill = 선거구명)) +
    geom_col( width = 0.5 ) +
    facet_wrap(vars(선거구명), scales = "free") +
    labs(x = "") +
    theme_minimal() +
    scale_y_continuous(labels = scales::percent) +
    theme(legend.position = "none")

코드
    
gs_old |>   
  mutate(민주_득표율 = 민주당 / ,
         국힘_득표율 = 국민의힘 / ) |> 
  mutate(득표차 = 민주_득표율 - 국힘_득표율) |> 
  ggplot(aes(x = fct_reorder(읍면동명, 득표차), y = 득표차, fill = 선거구명)) +
    geom_col( width = 0.5 ) +
    facet_wrap(vars(선거구명), scales = "free") +
    labs(x = "") +
    theme_minimal() +
    scale_y_continuous(labels = scales::percent) +
    theme(legend.position = "none")

6.2 투표율과 득표차

코드
gs_old |>   
  mutate(민주_득표율 = 민주당 / ,
         국힘_득표율 = 국민의힘 / ) |> 
  mutate(득표차 = 민주_득표율 - 국힘_득표율) |> 
  mutate(투표율 = 투표수 / 선거인수) |> 
  select(선거구명, 선거인수, 읍면동명, 득표차, 투표율) |> 
  ggplot(aes(x = 투표율, y = 득표차, color = 선거구명)) +
    geom_point(aes(size = 선거인수)) +
    facet_wrap(vars(선거구명)) +
    geom_text_repel(aes(label = 읍면동명)) +
    theme_minimal() +
    theme(legend.position = "top") +
    scale_x_continuous(labels = scales::percent) +
    scale_y_continuous(labels = scales::percent) +
    labs(x = "투표율", y = "득표차",
         title = "강서구 제21대 총선 투표율과 득표차",
         subtitle = "득표차 = 민주당 후보 득표율 - 국힘 후보 득표율 ") +
    guides(color = FALSE, size = guide_legend(nrow = 1)) +
    scale_size_continuous(labels = scales::comma)

7 비교

코드
gs_by_election <- gs_tbl |> 
  mutate(민주_득표율 = 민주당 / ,
         국힘_득표율 = 국민의힘 / ) |> 
  mutate(득표차 = 민주_득표율 - 국힘_득표율) |> 
  select(선거구명, 읍면동명, 선거인수, 투표수, 투표율, 민주_득표율, 국힘_득표율, 득표차) |> 
  mutate(선거 = "보궐선거")

gs_2020 <- gs_old |> 
  mutate(민주_득표율 = 민주당 / ,
         국힘_득표율 = 국민의힘 / ) |> 
  mutate(득표차 = 민주_득표율 - 국힘_득표율) |> 
  select(선거구명, 읍면동명, 선거인수, 투표수, 투표율, 민주_득표율, 국힘_득표율, 득표차) |> 
  mutate(선거 = "21대총선")

gs_total <- bind_rows(gs_2020,  gs_by_election)

7.1 투표율

코드
gs_total |> 
  select(읍면동명, 선거, 투표율) |> 
  pivot_wider(names_from = 선거, values_from = 투표율) |> 
  ggplot(aes(x=`21대총선`, y = 보궐선거)) +
    geom_point() +
    geom_smooth(method = lm, se = FALSE) +
    geom_text_repel(aes(label = 읍면동명))

7.2 득표차

코드
gs_total |> 
  select(읍면동명, 선거, 득표차) |> 
  pivot_wider(names_from = 선거, values_from = 득표차) |> 
  ggplot(aes(x=`21대총선`, y = 보궐선거)) +
    geom_point() +
    geom_smooth(method = lm, se = FALSE) +
    geom_text_repel(aes(label = 읍면동명))

7.3 정당지지율

7.3.1 민주당

코드
gs_total |> 
  select(선거구명, 읍면동명, 선거, 민주_득표율) |> 
  pivot_wider(names_from = 선거, values_from = 민주_득표율) |> 
  ggplot(aes(x=`21대총선`, y = 보궐선거)) +
    geom_point() +
    geom_smooth(method = lm, se = FALSE) +
    geom_text_repel(aes(label = 읍면동명)) +
    facet_wrap(~선거구명, scales = "free")

7.3.2 국민의힘

코드
gs_total |> 
  select(선거구명, 읍면동명, 선거, 국힘_득표율) |> 
  pivot_wider(names_from = 선거, values_from = 국힘_득표율) |> 
  ggplot(aes(x=`21대총선`, y = 보궐선거)) +
    geom_point() +
    geom_smooth(method = lm, se = FALSE) +
    geom_text_repel(aes(label = 읍면동명)) +
    facet_wrap(~선거구명, scales = "free")

7.3.3 모두

코드
gs_total |> 
  select(선거구명, 읍면동명, 선거, 민주_득표율, 국힘_득표율) |>
  pivot_longer(민주_득표율:국힘_득표율, names_to = "정당", values_to = "득표율") |> 
  pivot_wider(names_from = 선거, values_from = 득표율) |> 
  ggplot(aes(x=`21대총선`, y = 보궐선거, color = 정당)) +
    geom_point() +
    geom_smooth(method = lm, se = FALSE) +
    geom_text_repel(aes(label = 읍면동명)) +
    facet_wrap(~선거구명, scales = "free")

8 시각화

8.1 강서구갑

코드
gs_total |> 
  filter(선거구명 == "강서구갑") |> 
  select(선거구명, 읍면동명, 선거, 민주_득표율, 국힘_득표율) |>
  pivot_longer(민주_득표율:국힘_득표율, names_to = "정당", values_to = "득표율") |> 
  ggplot(aes(x = 선거, y = 득표율, group = 정당, color = 정당)) +
    geom_point() +
    geom_line() +
    facet_wrap(vars(읍면동명), scales = "fixed")

8.2 강서구을

코드
gs_total |> 
  filter(선거구명 == "강서구을") |> 
  select(선거구명, 읍면동명, 선거, 민주_득표율, 국힘_득표율) |>
  pivot_longer(민주_득표율:국힘_득표율, names_to = "정당", values_to = "득표율") |> 
  ggplot(aes(x = 선거, y = 득표율, group = 정당, color = 정당)) +
    geom_point() +
    geom_line() +
    facet_wrap(vars(읍면동명), scales = "fixed")

8.3 강서구병

코드
gs_total |> 
  filter(선거구명 == "강서구병") |> 
  select(선거구명, 읍면동명, 선거, 민주_득표율, 국힘_득표율) |>
  pivot_longer(민주_득표율:국힘_득표율, names_to = "정당", values_to = "득표율") |> 
  ggplot(aes(x = 선거, y = 득표율, group = 정당, color = 정당)) +
    geom_point() +
    geom_line() +
    facet_wrap(vars(읍면동명), scales = "fixed")