대통령 거부권

김건희 특검 거부권에 대해서 알아보자.

저자
소속

1 예비/정식 후보

국회의원 선거에서 예비 후보와 정식 후보는 몇가지 차이가 있다.

  1. 예비 후보 등록: 선거에 참여하고자 하는 개인은 먼저 ’예비 후보자’로 등록해야 합니다. 이 단계에서 그들은 법적으로 선거 운동을 할 수 있는 자격을 얻게 됩니다. 예비 후보 등록은 선거일로부터 몇 개월 전에 시작됩니다. 예비 후보자는 선거운동에 필요한 기본적인 활동을 할 수 있으나, 아직 정식 후보자로 선정되지 않았기 때문에 제한적인 활동만 가능합니다.

  2. 정식 후보자 선정: 선거일에 가까워지면, 각 정당은 자신들의 정식 후보자를 선정합니다. 이 과정은 당내 경선, 지명, 또는 다른 방식으로 이루어질 수 있습니다. 정식 후보자가 되면, 그 사람은 해당 선거구에서 그 정당을 대표하는 공식 후보가 됩니다.

차이점은 주로 이 두 단계에서 나타납니다:

  • 활동 범위: 예비 후보는 선거운동 활동이 제한적이며, 주로 자신을 알리고 지지를 호소하는 데 중점을 둡니다. 반면 정식 후보는 보다 광범위한 선거 운동을 할 수 있습니다.

  • 공식적 지위: 정식 후보는 해당 정당의 공식적인 지지를 받으며, 선거에서 승리할 경우 국회의원이 됩니다. 예비 후보는 아직 그 단계에 이르지 못한 상태입니다.

2 데이터셋

2.1 스크립트

코드
library(tidyverse)
library(testthat)
library(krvote)
library(httr)
library(jsonlite)

# 변수 설정
params <- list(
  serviceKey = Sys.getenv("DATA_GO_DECODE_KEY"),
  pageNo = 1,
  numOfRows = 10,
  resultType = "json",
  sgId = "20220309",
  sgTypecode = 1,
  sggName = "대한민국",
  sdName = "전국"
)

# GET 요청, params 사용
response <- GET("http://apis.data.go.kr/9760000/PofelcddInfoInqireService/getPofelcddRegistSttusInfoInqire", query = params)

candidates <- content(response, "text") |> 
  fromJSON() %>% 
  .$getPofelcddRegistSttusInfoInqire %>% 
  .$item  %>% 
  as_tibble() |> 
  select(giho, jdName, name, hanjaName, gender, birthday, age, addr)

candidates
#> # A tibble: 10 × 8
#>    giho  jdName         name   hanjaName gender birthday age   addr             
#>    <chr> <chr>          <chr>  <chr>     <chr>  <chr>    <chr> <chr>            
#>  1 1     더불어민주당   이재명 李在明    남     19641222 57    경기도 성남시 분…
#>  2 10    신자유민주연합 김경재 金景梓    남     19421103 79    서울특별시 영등… 
#>  3 11    우리공화당     조원진 趙源震    남     19590107 63    대구광역시 달서… 
#>  4 12    진보당         김재연 金在姸    여     19801030 41    경기도 의정부시 …
#>  5 13    통일한국당     이경희 李京熹    남     19740120 48    서울특별시 강남… 
#>  6 14    한류연합당     김민찬 金旻澯    남     19580204 64    서울특별시 동대… 
#>  7 2     국민의힘       윤석열 尹錫悅    남     19601218 61    서울특별시 서초… 
#>  8 3     정의당         심상정 沈相奵    여     19590220 63    경기도 고양시 덕…
#>  9 4     국민의당       안철수 安哲秀    남     19620122 60    서울특별시 노원… 
#> 10 5     기본소득당     오준호 吳準鎬    남     19750620 46    경기도 안산시 상…

3 선거 마스터 데이터

3.1 선거코드 마스터

코드
# 변수 설정
params <- list(
  pageNo = 1,
  numOfRows = 1000,
  resultType = "json",
  serviceKey = Sys.getenv("DATA_GO_DECODE_KEY")
)

# GET 요청
response <- GET("http://apis.data.go.kr/9760000/CommonCodeService/getCommonSgCodeList", 
                query = params)


election_codes <- content(response, "text") |> 
  fromJSON() %>% 
  .$getCommonSgCodeList %>% 
  .$item  %>% 
  as_tibble() 

election_codes |> 
  write_csv("data/선거API_선거코드.csv")

3.2 선거구 마스터

3.2.1 국회의원 선거구

코드
# 쿼리 매개변수 설정
params <- list(
  serviceKey = Sys.getenv("DATA_GO_DECODE_KEY"),
  pageNo = 1,
  numOfRows = 1000,
  resultType = "json",
  sgId = "20160413",
  sgTypecode = 2
)

# GET 요청
response <- GET("http://apis.data.go.kr/9760000/CommonCodeService/getCommonSggCodeList", 
                query = params)

precincts <- content(response, "text") |> 
  fromJSON() %>% 
  .$getCommonSggCodeList %>% 
  .$item  %>% 
  as_tibble() 

precincts
#> # A tibble: 253 × 8
#>    num   sgId     sgTypecode sggName      sdName     wiwName  sggJungsu sOrder
#>    <chr> <chr>    <chr>      <chr>        <chr>      <chr>    <chr>     <chr> 
#>  1 1     20160413 2          종로구       서울특별시 종로구   1         1     
#>  2 2     20160413 2          중구성동구갑 서울특별시 성동구   1         2     
#>  3 3     20160413 2          중구성동구을 서울특별시 중구     1         3     
#>  4 4     20160413 2          용산구       서울특별시 용산구   1         4     
#>  5 5     20160413 2          광진구갑     서울특별시 광진구   1         5     
#>  6 6     20160413 2          광진구을     서울특별시 광진구   1         6     
#>  7 7     20160413 2          동대문구갑   서울특별시 동대문구 1         7     
#>  8 8     20160413 2          동대문구을   서울특별시 동대문구 1         8     
#>  9 9     20160413 2          중랑구갑     서울특별시 중랑구   1         9     
#> 10 10    20160413 2          중랑구을     서울특별시 중랑구   1         10    
#> # ℹ 243 more rows

3.2.2 선거구 함수

코드

get_precincts <- function(sgId = "20160413") {
  params <- list(
    serviceKey = Sys.getenv("DATA_GO_DECODE_KEY"),
    pageNo = 1,
    numOfRows = 1000,
    resultType = "json",
    sgId = sgId,
    sgTypecode = 2
  )
  
  response <- GET("http://apis.data.go.kr/9760000/CommonCodeService/getCommonSggCodeList", 
                  query = params)
  
  precincts <- content(response, "text") |> 
    fromJSON() %>% 
    .$getCommonSggCodeList %>% 
    .$item  %>% 
    as_tibble() 
  
  return(precincts)
}

# write test case for get_precints
test_that("get_precincts returns a tibble", {
  expect_that(get_precincts("20160413"), is_a("tbl_df"))
})
#> Test passed 🌈

test_that("get_precincts returns a tibble with 253 rows", {
  expect_that(get_precincts("20160413") |> nrow(), equals(253))
})
#> Test passed 🎊

3.2.3 총선 전체 선거구

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

chongsun_codes <- election_codes |> 
  filter(sgTypecode == 0,
         str_detect(sgName, "국회의원"))

chongsun_precincts <- chongsun_codes |> 
  select(-num, -sgVotedate) |> 
  mutate(data = map(sgId, get_precincts)) 

chongsun_precincts |>
  write_rds("data/선거API_총선_전체선거구.rds")

3.3 후보자

예비후보자 정보는 없음.

3.3.1 스크립트

코드

# 쿼리 매개변수 설정
params <- list(
  serviceKey = Sys.getenv("DATA_GO_DECODE_KEY"),
  pageNo = 1,
  numOfRows = 1000,
  resultType = 'json',
  sgId = "20200415",
  sgTypecode = 2,
  sggName = "종로구",
  sdName = "서울특별시"
)

# GET 요청
response <- GET("http://apis.data.go.kr/9760000/PofelcddInfoInqireService/getPofelcddRegistSttusInfoInqire", query = params)

content(response, "text") |> 
    fromJSON() %>% 
    .$getPofelcddRegistSttusInfoInqire %>% 
    .$item  %>% 
    as_tibble() 
#> # A tibble: 12 × 23
#>    num   sgId   sgTypecode huboid sggName sdName wiwName giho  gihoSangse jdName
#>    <chr> <chr>  <chr>      <chr>  <chr>   <chr>  <chr>   <chr> <chr>      <chr> 
#>  1 1     20200… 2          10013… 종로구  서울…  종로구  1     ""         더불… 
#>  2 2     20200… 2          10013… 종로구  서울…  종로구  10    ""         공화당
#>  3 3     20200… 2          10013… 종로구  서울…  종로구  11    ""         국가… 
#>  4 4     20200… 2          10013… 종로구  서울…  종로구  12    ""         국민… 
#>  5 5     20200… 2          10013… 종로구  서울…  종로구  13    ""         기독… 
#>  6 6     20200… 2          10013… 종로구  서울…  종로구  14    ""         민중… 
#>  7 7     20200… 2          10013… 종로구  서울…  종로구  15    ""         한나… 
#>  8 8     20200… 2          10013… 종로구  서울…  종로구  16    ""         무소속
#>  9 9     20200… 2          10013… 종로구  서울…  종로구  2     ""         미래… 
#> 10 10    20200… 2          10013… 종로구  서울…  종로구  7     ""         우리… 
#> 11 11    20200… 2          10013… 종로구  서울…  종로구  8     ""         민중당
#> 12 12    20200… 2          10013… 종로구  서울…  종로구  9     ""         가자!…
#> # ℹ 13 more variables: name <chr>, hanjaName <chr>, gender <chr>,
#> #   birthday <chr>, age <chr>, addr <chr>, jobId <chr>, job <chr>, eduId <chr>,
#> #   edu <chr>, career1 <chr>, career2 <chr>, status <chr>

3.3.2 함수

코드

get_candidates <- function(sgId = "20200415", 
                           sggName ="종로구",
                           sdName = "서울특별시") {
  
  # 쿼리 매개변수 설정
  params <- list(
    serviceKey = Sys.getenv("DATA_GO_DECODE_KEY"),
    pageNo = 1,
    numOfRows = 1000,
    resultType = 'json',
    sgId = sgId,
    sgTypecode = 2,
    sggName = sggName,
    sdName = sdName
  )
  
  # GET 요청
  response <- GET("http://apis.data.go.kr/9760000/PofelcddInfoInqireService/getPofelcddRegistSttusInfoInqire", query = params)
  
  candidates <- content(response, "text") |> 
      fromJSON() %>% 
      .$getPofelcddRegistSttusInfoInqire %>% 
      .$item  %>% 
      as_tibble() 
  
  return(candidates)
}

get_candidates("20160413", "종로구", "서울특별시") 
#> # A tibble: 10 × 23
#>    num   sgId   sgTypecode huboid sggName sdName wiwName giho  gihoSangse jdName
#>    <chr> <chr>  <chr>      <chr>  <chr>   <chr>  <chr>   <chr> <chr>      <chr> 
#>  1 1     20160… 2          10011… 종로구  서울…  종로구  1     ""         새누… 
#>  2 2     20160… 2          10012… 종로구  서울…  종로구  10    ""         무소속
#>  3 3     20160… 2          10011… 종로구  서울…  종로구  2     ""         더불… 
#>  4 4     20160… 2          10011… 종로구  서울…  종로구  3     ""         국민… 
#>  5 5     20160… 2          10012… 종로구  서울…  종로구  4     ""         정의당
#>  6 6     20160… 2          10012… 종로구  서울…  종로구  5     ""         노동당
#>  7 7     20160… 2          10011… 종로구  서울…  종로구  6     ""         녹색당
#>  8 8     20160… 2          10012… 종로구  서울…  종로구  7     ""         진리… 
#>  9 9     20160… 2          10012… 종로구  서울…  종로구  8     ""         한나… 
#> 10 10    20160… 2          10011… 종로구  서울…  종로구  9     ""         무소속
#> # ℹ 13 more variables: name <chr>, hanjaName <chr>, gender <chr>,
#> #   birthday <chr>, age <chr>, addr <chr>, jobId <chr>, job <chr>, eduId <chr>,
#> #   edu <chr>, career1 <chr>, career2 <chr>, status <chr>

3.3.3 전체 후보

코드
chongsun_precincts <- 
  read_rds("data/선거API_총선_전체선거구.rds")

chongsun_candidates <- chongsun_precincts |> 
  select(data) |> 
  unnest(data) |>
  select(-sggJungsu, -sOrder) |>
  mutate(data = pmap(list(sgId, sggName, sdName), get_candidates))

chongsun_candidates |> 
  write_rds("data/선거API_총선_전체후보.rds")

3.4 당선인

3.4.1 스크립트

코드

# 쿼리 매개변수 설정
params <- list(
  serviceKey = Sys.getenv("DATA_GO_DECODE_KEY"),
  pageNo = 1,
  numOfRows = 1000,
  resultType = 'json',
  sgId = "20200415",
  sgTypecode = 2,
  sggName = "종로구",
  sdName = "서울특별시"
)

# GET 요청
response <- GET("http://apis.data.go.kr/9760000/WinnerInfoInqireService2/getWinnerInfoInqire", query = params)

content(response, "text") |> 
    fromJSON() %>% 
    .$getWinnerInfoInqire %>% 
    .$item  %>% 
    as_tibble() 
#> # A tibble: 1 × 24
#>   num   sgId    sgTypecode huboid sggName sdName wiwName giho  gihoSangse jdName
#>   <chr> <chr>   <chr>      <chr>  <chr>   <chr>  <chr>   <chr> <chr>      <chr> 
#> 1 1     202004… 2          10013… 종로구  서울…  종로구  1     ""         더불… 
#> # ℹ 14 more variables: name <chr>, hanjaName <chr>, gender <chr>,
#> #   birthday <chr>, age <chr>, addr <chr>, jobId <chr>, job <chr>, eduId <chr>,
#> #   edu <chr>, career1 <chr>, career2 <chr>, dugsu <chr>, dugyul <chr>

3.4.2 함수

코드

get_winner <- function(sgId = "20200415", 
                           sggName ="종로구",
                           sdName = "서울특별시") {
  
  # 쿼리 매개변수 설정
  params <- list(
    serviceKey = Sys.getenv("DATA_GO_DECODE_KEY"),
    pageNo = 1,
    numOfRows = 1000,
    resultType = 'json',
    sgId = sgId,
    sgTypecode = 2,
    sggName = sggName,
    sdName = sdName
  )
  
  # GET 요청
  response <- GET("http://apis.data.go.kr/9760000/WinnerInfoInqireService2/getWinnerInfoInqire", query = params)
  
  winner <- content(response, "text") |> 
      fromJSON() %>% 
      .$getWinnerInfoInqire %>% 
      .$item  %>% 
      as_tibble() 
  
  return(winner)
}

get_winner("20160413", "성남시분당구을", "경기도") 
#> # A tibble: 1 × 24
#>   num   sgId    sgTypecode huboid sggName sdName wiwName giho  gihoSangse jdName
#>   <chr> <chr>   <chr>      <chr>  <chr>   <chr>  <chr>   <chr> <chr>      <chr> 
#> 1 1     201604… 2          10011… 성남시… 경기도 성남시… 2     ""         더불… 
#> # ℹ 14 more variables: name <chr>, hanjaName <chr>, gender <chr>,
#> #   birthday <chr>, age <chr>, addr <chr>, jobId <chr>, job <chr>, eduId <chr>,
#> #   edu <chr>, career1 <chr>, career2 <chr>, dugsu <chr>, dugyul <chr>

3.4.3 전체 당선인

코드
chongsun_precincts <- 
  read_rds("data/선거API_총선_전체선거구.rds")

chongsun_winners <- chongsun_precincts |> 
  select(data) |> 
  unnest(data) |>
  select(-sggJungsu, -sOrder) |>
  mutate(data = pmap(list(sgId, sggName, sdName), get_winner))

chongsun_winners |> 
  write_rds("data/선거API_총선_전체당선인.rds")

4 분석

4.1 당선확률 추세

::::: {.callout-note}

  1. 민주당 (1991-1995): 1991년에 창당된 민주당은 1990년대 초반 대한민국 정치에 중요한 역할을 했습니다.

  2. 국민회의 (1995-2000): 민주당은 1995년 김대중 대통령 후보의 지도 하에 국민회의로 이름을 바꿨습니다.

  3. 새천년민주당 (2000-2003): 2000년, 국민회의는 새천년민주당으로 개편되었습니다.

  4. 열린우리당 (2003-2007): 2003년, 새천년민주당은 열린우리당으로 당명을 변경하며 새로운 정체성을 추구했습니다.

  5. 통합민주당 (2008-2011): 열린우리당은 2008년 통합민주당으로 개편되었습니다.

  6. 민주통합당 (2011-2013): 2011년, 통합민주당은 민주통합당으로 명칭을 바꿨습니다.

  7. 더불어민주당 (2015-현재): 민주통합당은 2014년에 새정치민주연합으로 잠시 명칭을 변경했다가, 2015년에 현재의 더불어민주당으로 최종적으로 당명을 변경했습니다.

  1. 한나라당 (1997-2012): 한나라당은 1997년에 창당되었으며, 이후 대한민국 보수 정당의 주류를 이루었습니다.

  2. 새누리당 (2012-2017): 한나라당은 2012년, 새누리당으로 당명을 변경했습니다. 이는 새로운 이미지와 정치적 방향성을 반영하기 위한 조치였습니다.

  3. 자유한국당 (2017-2020): 새누리당은 2017년, 자유한국당으로 재창당하며 보수적 가치와 정체성에 더욱 무게를 두었습니다.

  4. 미래통합당 (2020): 자유한국당은 2020년 초, 미래통합당으로 재창당하며 보수 진영의 다양한 세력을 통합하려는 노력의 일환으로 이 당명을 사용했습니다.

  5. 국민의힘 (2020-현재): 같은 해인 2020년에, 미래통합당은 국민의힘으로 다시 한 번 당명을 변경했습니다. 이는 보다 폭넓은 국민적 지지를 얻고자 하는 노력의 일환으로, 현재까지 이 당명을 사용하고 있습니다.

4.2 데이터셋

4.2.1 후보

코드
candidates <- 
  read_rds("data/선거API_총선_전체후보.rds") 

hubos <- candidates |> 
  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, status) 

4.2.2 당선인

코드
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, dugsu, dugyul) 

4.2.3 후보 + 당선인

코드
chongsun_precincts <- 
  read_rds("data/선거API_총선_전체선거구.rds")

winners_gt <- hubos |> 
  left_join(winners, by = c("sgId", "sdName", "sggName", "jdName", "정당", "name")) |> 
  mutate(당선 = ifelse(!is.na(dugsu), "당선", "낙선")) |> 
  count(sgId, 정당, 당선) |> 
  pivot_wider(names_from = 당선, values_from = n)  |> 
  mutate(당선확률 = 당선 / (당선 + 낙선)) |> 
  left_join(chongsun_precincts |> mutate(sgId = as.character(sgId)) |> select(sgId, sgName), by = "sgId") |> 
  mutate(sgName = str_replace(sgName, " 국회의원선거", "")) |>
  pivot_wider(names_from = 정당, values_from = c(당선확률, 낙선, 당선)) |> 
  gt() |> 
  gtExtras::gt_merge_stack(col1 = sgName, col2 = sgId) |> 
  fmt_percent(columns = c(당선확률_국민의힘, 당선확률_민주당, 당선확률_기타), decimals = 1) |>
  tab_spanner(label = "당선", columns = c(당선_국민의힘, 당선_민주당, 당선_기타)) |>
  tab_spanner(label = "낙선", columns = c(낙선_국민의힘, 낙선_민주당, 낙선_기타)) |> 
  tab_spanner(label = "당선확률", columns = c(당선확률_국민의힘, 당선확률_민주당, 당선확률_기타)) |>
  cols_label(sgName = "선거명", 
             당선_국민의힘 = "국힘", 
             당선_민주당 = "민주", 
             당선_기타 = "기타", 
             당선확률_국민의힘 = "국힘", 
             당선확률_민주당 = "민주", 
             당선확률_기타 = "기타", 
             낙선_국민의힘 = "국힘", 
             낙선_민주당 = "민주", 
             낙선_기타 = "기타") |>
  cols_move(
    columns = c(당선확률_국민의힘, 당선확률_민주당, 당선확률_기타),
    after = 당선_기타
  ) |>
  cols_move(
    columns = c(낙선_국민의힘, 낙선_민주당, 낙선_기타),
    after = 당선_기타
  ) |>
  gt_theme_hangul() |> 
  tab_style(
    style = cell_text(color = "red", weight = "bold"),
    locations = cells_body(
      columns = c(당선확률_국민의힘, 당선_국민의힘, 낙선_국민의힘)
    )
  ) |> 
  tab_style(
    style = cell_text(color = "blue", weight = "bold"),
    locations = cells_body(
      columns = c(당선확률_민주당, 당선_민주당, 낙선_민주당)
    )
  )  |>
  tab_header(title = "역대 국회의원 선거 정당후보 당선확률") 

winners_gt
역대 국회의원 선거 정당후보 당선확률
선거명 당선 낙선 당선확률
국힘 민주 기타 국힘 민주 기타 국힘 민주 기타
제16대
20000413
112 96 19 113 129 571 49.8% 42.7% 3.2%
제17대
20040415
100 129 14 118 114 700 45.9% 53.1% 2.0%
제18대
20080409
131 66 48 114 131 629 53.5% 33.5% 7.1%
제19대
20120411
127 106 13 104 104 474 55.0% 50.5% 2.7%
제20대
20160413
105 110 38 147 125 419 41.7% 46.8% 8.3%
제21대
20200415
84 163 6 157 90 618 34.9% 64.4% 1.0%
코드


winners_gt |> 
  gt::gtsave("images/특검법_역대_국회의원_정당후보_당선확률.png")

4.3 정당별 당선확률

코드
library(ggrepel)

winner_party_g <- hubos |> 
  left_join(winners, by = c("sgId", "sdName", "sggName", "jdName", "정당", "name")) |> 
  mutate(당선 = ifelse(!is.na(dugsu), "당선", "낙선")) |> 
  count(sgId, 정당, 당선) |> 
  left_join(chongsun_precincts |> mutate(sgId = as.character(sgId)) |> select(sgId, sgName), by = "sgId") |> 
  mutate(sgName = str_replace(sgName, " 국회의원선거", "")) |>
  pivot_wider(names_from = 당선, values_from = n)  |> 
  mutate(당선확률 = 당선 / (당선 + 낙선)) |>
  ggplot(aes(x = sgName, y = 당선확률, color = 정당, group = 정당)) +
    geom_line() +
    geom_point(size = 3) +
    scale_y_continuous(labels = scales::percent_format(accuracy = 1))  +
    labs(x = "",
         y = "당선확률",
         title = "정당별 당선확률") +
    theme_korean() +
    scale_color_manual(values = c("민주당" = "#0054A6", 
                                  "국민의힘" = "#E2231A", 
                                  "기타" = "#999999")) +
    theme(legend.position = "top") +
    geom_text_repel(data = . %>% filter(당선확률 > 0.2),
                    aes(label = scales::percent(당선확률, accuracy = 0.1),
                        color = 정당),
                    nudge_x = 0.2,
                    nudge_y = 0.02,
                    size = 5,
                    color = "black",
                    fontface = "bold",
                    segment.size = 0.2,
                    segment.color = "grey50",
                    segment.curvature = 0.2,
                    segment.ncp = 5,
                    box.padding = 0.5,
                    point.padding = 0.5,
                    point.size = 0.2,
                    force = 0.5,
                    seed = 123,
                    max.overlaps = Inf) 

winner_party_g

코드

ragg::agg_jpeg("images/특별법_정당별_당선확률.jpeg",
               width = 10, height = 7, units = "in", res = 600)
winner_party_g
dev.off()    
#> png 
#>   2

4.4 권역별 당선확률

코드

region_party_g <- hubos |> 
  left_join(winners, by = c("sgId", "sdName", "sggName", "jdName", "정당", "name")) |> 
  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_ # 기타 경우에 대한 처리
)) |> 
  count(sgId, 권역, 정당, 당선) |> 
  left_join(chongsun_precincts |> mutate(sgId = as.character(sgId)) |> select(sgId, sgName), by = "sgId") |> 
  mutate(sgName = str_replace(sgName, " 국회의원선거", "")) |>
  pivot_wider(names_from = 당선, values_from = n, values_fill = 0)  |> 
  mutate(당선확률 = 당선 / (당선 + 낙선)) |>
  mutate(정당 = factor(정당, levels = c("민주당", "국민의힘", "기타"))) |>
  mutate(권역 = factor(권역, levels = c("대구경북", "부울경", "수도권",
                                    "광주전라", "대전충청세종", "강원제주"))) |>
  mutate(권역 = fct_relevel(권역, "대구경북", "부울경", "수도권",
                                    "광주전라", "대전충청세종", "강원제주")) |>  
  ggplot(aes(x = sgName, y = 당선확률, color = 정당, group = 정당)) +
    geom_line() +
    geom_point(size = 3) +
    scale_y_continuous(labels = scales::percent_format(accuracy = 1),
                       limits = c(0, 1.1))  +
    labs(x = "",
         y = "당선확률",
         title = "권역별 당선확률") +
    theme_korean() +
    scale_color_manual(values = c("민주당" = "#0054A6", 
                                  "국민의힘" = "#E2231A", 
                                  "기타" = "#999999")) +
    theme(legend.position = "top",
          strip.text = element_text(size = 10)) +
    geom_text_repel(data = . %>% filter(당선확률 > 0.2),
                    aes(label = scales::percent(당선확률, accuracy = 0.1),
                        color = 정당),
                    nudge_x = 0.2,
                    nudge_y = 0.02,
                    size = 3.5,
                    color = "black",
                    fontface = "bold",
                    segment.size = 0.2,
                    segment.color = "grey50",
                    segment.curvature = 0.2,
                    segment.ncp = 5,
                    box.padding = 0.5,
                    point.padding = 0.5,
                    point.size = 0.2,
                    force = 0.5,
                    seed = 123,
                    max.overlaps = Inf) +
  facet_wrap(~권역, ncol = 2, scales = "free_x")

region_party_g

코드

ragg::agg_jpeg("images/특별법_권역별_당선확률.jpeg",
               width = 10, height = 7, units = "in", res = 600)
region_party_g
dev.off()    
#> png 
#>   2