대구경북/부울경

대구경북/부울경 김건희 특검 거부권에 대해서 알아보자.

저자
소속

1 대구경북, 부울경

제21대 2020년 총선 기준 대구경북과 부울경 선거구수는 다음과 같다.

지역 선거구 수
부산 18개
울산 6개
경남 16개
부산울산경남 부분합 40개
대구 12개
경북 13개
대구경북 부분합 25개
전체 총합 65개

2 데이터셋

코드
library(tidyverse)
library(ggrepel)

## 마스터 --------
election_codes <- 
  read_csv("data/선거API_선거코드.csv")


## 후보 --------
candidates_raw <- 
  read_rds("data/선거API_총선_전체후보.rds")

candidates <- candidates_raw |> 
  select(data) |> 
  unnest(data) |> 
  mutate(정당 = case_when(
    jdName %in% c("더불어민주당", "통합민주당", "민주통합당") ~ "민주당",
    jdName == "새천년민주당" & sgId == "20000413" ~ "민주당",
    jdName == "열린우리당" & sgId == "20040415" ~ "민주당",
    jdName %in% c("한나라당", "미래통합당", "새누리당", "자유한국당", "국민의힘") ~ "국민의힘",
    TRUE ~ "기타"
  )) |> 
  select(sgId, sdName, sggName, jdName, 정당, name, hanjaName, status) 


## 당선인 ------
winners_raw <- 
  read_rds("data/선거API_총선_전체당선인.rds")

winners  <- winners_raw |> 
  select(data) |> 
  unnest(data) |> 
  mutate(정당 = case_when(
    jdName %in% c("더불어민주당", "통합민주당", "민주통합당") ~ "민주당",
    jdName == "새천년민주당" & sgId == "20000413" ~ "민주당",
    jdName == "열린우리당" & sgId == "20040415" ~ "민주당",
    jdName %in% c("한나라당", "미래통합당", "새누리당", "자유한국당", "국민의힘") ~ "국민의힘",
    TRUE ~ "기타"
  )) |> 
  select(sgId, sdName, sggName, jdName, 정당, name, hanjaName, dugsu, dugyul) 

3 전처리

코드
basetable <- candidates |> 
  left_join(winners, by = c("sgId", "sdName", "sggName", "jdName", "정당", "name", "hanjaName")) |> 
  mutate(sdName = ifelse(str_detect(sdName, "제주"), "제주특별자치도", sdName)) |>
  mutate(당선여부 = ifelse(is.na(dugsu), "낙선", "당선")) |> 
    mutate(권역 = case_when(
  sdName %in% c("서울특별시", "인천광역시", "경기도") ~ "수도권",
  sdName %in% c("부산광역시", "울산광역시", "경상남도") ~ "부울경",
  sdName %in% c("광주광역시", "전라남도", "전라북도") ~ "광주전라",
  sdName %in% c("대구광역시", "경상북도") ~ "대구경북",  
  sdName %in% c("대전광역시", "충청남도", "충청북도", "세종특별자치시") ~ "대전충청세종",
  sdName %in% c("강원도", "제주특별자치도", "제주도") ~ "강원제주",  
  TRUE ~ NA_character_ # 기타 경우에 대한 처리
)) 

4 분석

4.1 사퇴비율

코드

resign_g <- basetable |> 
  count(권역, sdName, status) |> 
  pivot_wider(names_from = status, values_from = n, values_fill = 0) |> 
  mutate(사퇴비율 = 사퇴 / (사퇴 + 등록 + 등록무효)) |> 
  arrange(desc(사퇴비율)) |> 
  mutate(권역색상 = case_when(
    str_detect(권역, "대구|부울경") ~ "red",
    TRUE ~ "gray30"
  )) |> 
  # 사퇴비율 막대그래프 그려줘
  ggplot(aes(x = reorder(sdName, 사퇴비율), y = 사퇴비율,
             fill = 권역색상)) +
    geom_col() +
    geom_text(aes(label = scales::percent(사퇴비율, accuracy = 0.01),
                  color = 권역색상),
              vjust = +0.5, hjust = -0.2, size = 7) +
    coord_flip() +
    labs(
      title = "역대 총선 시도별 후보자 중 사퇴 비율",
      subtitle = "사퇴 비율 = 사퇴 / (사퇴 + 등록 + 등록무효)",
      x = "",
      y = "사퇴비율",
      caption = "자료출처: 중앙선거관리위원회"
    ) +
    theme_korean() +
    scale_y_continuous(labels = scales::percent_format(accuracy = 0.1),
                       limits = c(0, 0.021))  +
    scale_fill_manual(values = c("red" = "red", "gray30" = "gray30"),
                      guide = FALSE) +
    scale_color_manual(values = c("red" = "red", "gray30" = "gray30"),
                      guide = FALSE) 

resign_g

코드

ragg::agg_jpeg("images/특별법_후보자_사퇴비율.jpeg",
               width = 10, height = 7, units = "in", res = 600)
resign_g
dev.off()    
#> png 
#>   2

4.2 대구경북 당선자

코드
tk_g <- basetable |> 
  mutate(sggName = str_replace_all(sggName, "[^가-힣]", "")) |> 
  mutate(당선인 = str_glue("{name}\n{hanjaName}")) |>
  filter(str_detect(sdName, "대구광역시|경상북도"),
         당선여부 == "당선") |>
  mutate(선거구 = str_glue("{sdName} {sggName}")) |> 
  left_join(election_codes |> 
              filter(sgTypecode == 0) |> 
              select(sgId, sgName) |> 
              mutate(sgId = as.character(sgId)), by = "sgId") |>
  mutate(선거명 = str_remove(sgName, " 국회의원선거")) |> 
  mutate(정당 = factor(정당, levels = c("국민의힘", "민주당", "기타"))) |> 
  ggplot(aes(x = 선거명, y = 선거구, group = 당선인, color = 정당)) +
    geom_text_repel(aes(label = name), size = 3)  +
    geom_line() +
    geom_point() +
    theme_korean() +
    theme(legend.position = "top",
          axis.text.x = element_text(size = 7),
          axis.text.y = element_text(size = 7)) +
    labs(
      title = "대구광역시, 경상북도 선거구 당선자",
      x = "",
      y = "",
      caption = "자료출처: 중앙선거관리위원회"
    ) +
    scale_color_manual(values = c("국민의힘" = "red", 
                                  "민주당"   = "blue",
                                  "기타" = "gray10")) 

tk_g

코드

ragg::agg_jpeg("images/특별법_후보자_대구경북.jpeg",
               width = 10, height = 7, units = "in", res = 600)
tk_g
dev.off()    
#> png 
#>   2

4.3 부울경 당선자

코드
bwk_g <- basetable |> 
  mutate(sggName = str_replace_all(sggName, "[^가-힣]", "")) |> 
  mutate(당선인 = str_glue("{name}\n{hanjaName}")) |>
  filter(str_detect(sdName, "부산광역시|경상남도|울산광역시"),
         당선여부 == "당선") |>
  mutate(선거구 = str_glue("{sdName} {sggName}")) |> 
  left_join(election_codes |> 
              filter(sgTypecode == 0) |> 
              select(sgId, sgName) |> 
              mutate(sgId = as.character(sgId)), by = "sgId") |>
  mutate(선거명 = str_remove(sgName, " 국회의원선거")) |> 
  mutate(정당 = factor(정당, levels = c("국민의힘", "민주당", "기타"))) |> 
  ggplot(aes(x = 선거명, y = 선거구, group = 당선인, color = 정당)) +
    geom_text_repel(aes(label = name), size = 2.5)  +
    geom_line() +
    geom_point() +
    theme_korean() +
    theme(legend.position = "top",
          axis.text.x = element_text(size = 7),
          axis.text.y = element_text(size = 6)) +
    labs(
      title = "부산/울산광역시, 경상남도 선거구 당선자",
      x = "",
      y = "",
      caption = "자료출처: 중앙선거관리위원회"
    ) +
    scale_color_manual(values = c("국민의힘" = "red", 
                                  "민주당"   = "blue",
                                  "기타" = "gray10")) 

bwk_g

코드

ragg::agg_jpeg("images/특별법_후보자_부울경.jpeg",
               width = 10, height = 7, units = "in", res = 600)
bwk_g
dev.off()    
#> png 
#>   2

4.4 재선비율

4.4.1 스크립트

코드

basetable |> 
  filter(sgId %in% c("20000413", "20040415")) |> 
  filter(당선여부 == "당선") |> 
  filter(sdName == "대구광역시") |> 
  select(sgId, name, 당선여부) |> 
  pivot_wider(names_from = sgId, values_from = 당선여부) |> 
  filter(!is.na(`20000413`)) |>
  mutate(재선여부 = ifelse(`20000413` == "당선" & 
                           !is.na(`20040415`), "재선", "탈락")) |> 
  count(재선여부) |> 
  mutate(재선비율 = n / sum(n)) |>
  filter(재선여부 == "재선") |> 
  pull(재선비율)
#> [1] 0.4545455

4.4.2 함수

코드

election_vector <- basetable |> 
  count(sgId) |> pull(sgId)

calculate_election <- function(old_election = "20000413", 
                               new_election = "20040415",
                               region = "대구광역시") {
  re_elected <- basetable |> 
    filter(sgId %in% c(old_election, new_election)) |> 
    filter(당선여부 == "당선") |> 
    filter(sdName == region) |> 
    select(sgId, name, 당선여부) |> 
    pivot_wider(names_from = sgId, values_from = 당선여부) |> 
    set_names(c("name", "oldElection", "newElection")) |> 
    filter(!is.na(oldElection)) |>  
    mutate(재선여부 = case_when(
      oldElection == "당선" & !is.na(newElection) ~ "재선", 
      TRUE ~ "탈락")) |> 
    count(재선여부) |>
    mutate(재선비율 = n / sum(n)) |>
    filter(재선여부 == "재선") |>
    pull(재선비율)
  
  if(identical(re_elected, numeric(0))) {
    return(0)
  } else {
    return(re_elected)
  }
}

calculate_election(election_vector[2], election_vector[3], "광주광역시")
#> [1] 0.2857143
calculate_election(election_vector[5], election_vector[6], "울산광역시")
#> [1] 0.1666667
calculate_election(election_vector[5], election_vector[6], "부산광역시")
#> [1] 0.4444444
calculate_election(election_vector[5], election_vector[6], "광주광역시")
#> [1] 0

4.4.3 대구 함수

코드
election_vector |> 
  enframe(name = NULL, value = "election") |> 
  mutate(next_election = dplyr::lead(election))  |> 
  filter(!is.na(next_election)) |>
  mutate(data = map2_dbl(election, next_election, calculate_election)) 
#> # A tibble: 5 × 3
#>   election next_election  data
#>   <chr>    <chr>         <dbl>
#> 1 20000413 20040415      0.455
#> 2 20040415 20080409      0.583
#> 3 20080409 20120411      0.417
#> 4 20120411 20160413      0.417
#> 5 20160413 20200415      0.417

4.4.4 전국

코드
sdName_vector <- basetable |> 
  count(sdName) |> pull(sdName)

nomination <- election_vector |> 
  enframe(name = NULL, value = "election") |> 
  mutate(next_election = dplyr::lead(election)) |> 
  mutate(sdName = list(sdName_vector) ) |> 
  filter(!is.na(next_election)) |> 
  unnest(sdName) |> 
  filter(!sdName %in% c("세종특별자치시", "제주특별자치도")) |> 
  mutate(data = pmap(list(election, next_election, sdName), 
                     safely(calculate_election, otherwise = "error")))


nomination_g <- nomination |> 
  mutate(재선율 = map(data, ~.$result)) |> 
  unnest(재선율) |> 
  left_join(election_codes |> 
              filter(sgTypecode == 0) |> 
              select(sgId, sgName) |> 
              mutate(sgId = as.character(sgId)), by = c("next_election" = "sgId")) |>
  mutate(선거명 = str_remove(sgName, " 국회의원선거")) |>   
  mutate(sdName = factor(sdName, levels = 
                           c("대구광역시", "경상북도", 
                             "부산광역시", "울산광역시", "경상남도", 
                             "광주광역시", "전라남도", "전라북도", "강원도", 
                             "대전광역시",  "충청남도", "충청북도",
                             "서울특별시", "경기도", "인천광역시" ))) |>
  ggplot(aes(x = 선거명, y = 재선율, group = sdName, color = sdName)) +
    geom_line() +
    geom_point() +
    facet_wrap(~sdName, ncol = 5) +
    theme_korean() +
    scale_y_continuous(labels = scales::percent) +
    theme(legend.position = "none") +
    labs(
      title = "국회의원 선거 현역 재선비율",
      subtitle = "직전선거 당선자 중 다음 선거 당선자 비율",
      x = "",
      y = "재선비율",
      caption = "자료출처: 중앙선거관리위원회"
    ) +
    geom_hline(yintercept = 0.5, linetype = "dashed", color = "gray20") +
    theme(
      axis.text.x    = ggplot2::element_text(family = "MaruBuri", size = 8),
      axis.text.y    = ggplot2::element_text(family = "MaruBuri", size = 10)
    )

nomination_g

코드

ragg::agg_jpeg("images/특별법_현역의원_재선비율.jpeg",
               width = 10, height = 7, units = "in", res = 600)
nomination_g
dev.off()    
#> png 
#>   2