지역/당협 위원장

민주당 지역위원장과 국민의힘 당협위원장 현황을 살펴보자.

저자
소속

1 데이터

나무위키 지역/당협위원장을 통해 금일 기준(2023-09-29) 각 당별 현황을 파악해보자.

1.1 지역/당협위원장

코드
library(tidyverse)
library(rvest)
library(gt)
library(gtExtras)
library(rvest)

wiki_html <- read_html('https://namu.wiki/w/당협위원장/목록')

## 시도명 ------
sido_h3 <- wiki_html |> 
  html_elements("h3") |> 
  html_text()

sido_names <- sido_h3[str_detect(sido_h3, "^2")] |> 
  str_extract("[가-힣]+")

## 표 ------
######## 5: 서울특별시, 21: 제주도

get_result <- function(index){
  
    if(index == 18) { # 경상북도
      result <- wiki_html |>
        html_node(xpath = str_glue("/html/body/div/div/div[2]/div/div[1]/div[5]/div/div/div/div[3]/div/div/div/div/div/div/div/div/div/div[10]/div/div/div/div/div[1]/div/div[{index}]/div[4]/table")) |>
    html_table()
    } else {
      result  <- wiki_html |>
        html_node(xpath = str_glue("/html/body/div/div/div[2]/div/div[1]/div[5]/div/div/div/div[3]/div/div/div/div/div/div/div/div/div/div[10]/div/div/div/div/div[1]/div/div[{index}]/div[3]/table")) |>
        html_table()
    }
    return(result)
}

get_result(19)

district_raw <- tibble(시도코드 = 5:21) |> 
  mutate(data = map(시도코드, safely(get_result, otherwise="error")))

district_tbl <- district_raw |> 
  mutate(result = map(data, pluck, "result")) |> 
  mutate(tibble = map_lgl(result, is_tibble)) |> 
  dplyr::filter(tibble) |> 
  mutate(시도명 = sido_names) |> 
  select(시도명, result)

# district_tbl |>
#   write_rds("data/시도별_당협위원장.rds")

2 데이터 검정 및 전처리

코드
# 선거구 ---------
nec_precinct_total <- 
  read_rds("data/nec/선관위_당선인정보.rds")

precinct_tbl <- nec_precinct_total |> 
  dplyr::filter(sggName != "비례대표",
                sgId == "20200415") |> 
  count(sdName)

# 당협/지역 위원장

district_raw <- read_rds("data/시도별_당협위원장.rds")

district_tbl <- district_raw |> 
  unnest(result) |> 
  janitor::row_to_names(row_number = 1) |> 
  dplyr::filter(!지역구 %in% c("시당위원장", "도당위원장", "지역구") ) |> 
  rename("시도명" = "서울특별시") |> 
  mutate(민주당 = str_extract(더불어민주당, "[가-힣]+"),
         국민의힘 = str_extract(국민의힘, "[가-힣]+")) |> 
  select(-더불어민주당) |> 
  pivot_longer(cols = c(민주당, 국민의힘), names_to = "당명", values_to = "위원장")  |> 
  mutate(위원장 = ifelse(위원장 %in% c("공모", "공석", NA), NA_character_, 위원장))  

3 분석

3.1 공석 현황

코드
district_empty_gt <- district_tbl |> 
  group_by(당명) |> 
  summarise(공석 = sum(is.na(위원장))) |> 
  mutate(선거구수 = 253) |> 
  mutate(공석비율 = 공석 / 선거구수) |> 
  relocate(선거구수, .after = 당명) |>
  mutate(위원장수 = 선거구수 - 공석) |> 
  relocate(공석, .after = 위원장수) |>
  mutate(logo = c("images/party_power.jpg", "images/party_minju.png") ) |> 
  relocate(logo, .before = 당명) |>  
  arrange(공석비율) |> 
  gt() |> 
  gt_theme_hangul() |> 
  tab_header(title = "지역/당협위원장 현황") |>
  cols_label(당명 = "정당명",
             선거구수 = "선거구수",
             위원장수 = "위원장수",
             공석비율 = "공석비율",
             logo = " ") |> 
  fmt_percent(columns = "공석비율", decimals = 1) |> 
  tab_footnote(
    footnote = "나무위키: 당협위원장/목록",
    locations = cells_title(groups = "title")
  ) |> 
  tab_spanner(
    label = "인원",
    columns = c(
      선거구수, 위원장수, 공석
    )
  ) |> 
  tab_style(
    style = cell_text(color = "red", weight = "bold", size = "large"),
    locations = cells_body(
      columns = c(공석비율), 
      rows = 당명 == "국민의힘"
    )) |> 
  tab_style(
    style = cell_text(color = "blue", weight = "bold", size = "large"),
    locations = cells_body(
      columns = c(공석비율), 
      rows = 당명 == "민주당"
    )) |> 
    gt_img_rows(columns = logo, img_source = "local", height = 30) 

district_empty_gt
지역/당협위원장 현황1
정당명 인원 공석비율
선거구수 위원장수 공석
민주당 253 250 3 1.2%
국민의힘 253 225 28 11.1%
1 나무위키: 당협위원장/목록
코드

# district_empty_gt |>
#   gtsave("images/지역_당협위원장_공석현황.png")

3.2 권역별 공석현황

코드
## 선거구 권역별 정수
region_legislator <- nec_precinct_total |> 
  dplyr::filter(sggName != "비례대표",
                sgId == "20200415") |> 
  mutate(권역 = case_when(
    sdName %in% c("경기도", "서울특별시", "인천광역시") ~ "수도권",
    sdName %in% c("전라남도", "전라북도", "광주광역시") ~ "전라권",
    sdName %in% c("경상남도", "경상북도", "대구광역시", "부산광역시", "울산광역시") ~ "경상권",
    sdName %in% c("강원도", "세종특별자치시", "제주도", "제주특별자치도", "대전광역시", "충청남도", "충청북도") ~ "충청제주강원")) |> 
  count(권역, name = "정수")

## 지역/당협의원장 권역별 정수
region_district_tbl <- district_tbl |> 
  mutate(권역 = case_when(
    시도명 %in% c("경기도", "서울특별시", "인천광역시") ~ "수도권",
    시도명 %in% c("전라남도", "전라북도", "광주광역시") ~ "전라권",
    시도명 %in% c("경상남도", "경상북도", "대구광역시", "부산광역시", "울산광역시") ~ "경상권",
    시도명 %in% c("강원특별자치도", "세종특별자치시", "제주도", "제주특별자치도", "대전광역시", "충청남도", "충청북도") ~ "충청제주강원")) |> 
  group_by(당명, 권역) |> 
  summarise(공석 = sum(is.na(위원장))) |> 
  ungroup() |> 
  left_join(region_legislator) |> 
  pivot_wider(names_from = 당명, values_from = 공석)  |>
  mutate(국힘_위원장수 = 정수 - 국민의힘,
         민주_위원장수 = 정수 - 민주당) |>
  mutate(국힘_공석율 = 국민의힘 / 정수,
         민주_공석율 = 민주당 / 정수) |> 
  dplyr::select(권역, 정수, 민주_위원장수, 민주당, 민주_공석율,
                     국힘_위원장수, 국민의힘, 국힘_공석율)  |> 
  arrange(desc(정수))

region_district_tbl |> 
  janitor::adorn_totals()
#>          권역 정수 민주_위원장수 민주당 민주_공석율 국힘_위원장수 국민의힘
#>        수도권  121           118      3  0.02479339           102       19
#>        경상권   65            65      0  0.00000000            60        5
#>  충청제주강원   39            39      0  0.00000000            36        3
#>        전라권   28            28      0  0.00000000            27        1
#>         Total  253           250      3  0.02479339           225       28
#>  국힘_공석율
#>   0.15702479
#>   0.07692308
#>   0.07692308
#>   0.03571429
#>   0.34658523

## 공석 비율 표시하는 함수
grand_pcnt_func <- function(data) {
  empty_list <- data |> 
    summarise(민주_공석수 = sum(민주당),
              국힘_공석수 = sum(국민의힘)) |> 
    mutate(민주_공석율 = 민주_공석수 / 253,
           국힘_공석율 = 국힘_공석수 / 253) |> 
    select(민주_공석율, 국힘_공석율) |> 
    unlist()

  return (empty_list)
}  

region_district_gt <- region_district_tbl |> 
  gt() |> 
  gt_theme_hangul() |> 
  tab_header(title = "권역별 지역/당협위원장 현황") |>
  cols_align(columns = 권역, "center") |> 
  cols_label(권역 = "권역",
             정수 = "선거구수",
             국힘_위원장수 = "당협위원장수",
             민주_위원장수 = "지역위원장수",
             국민의힘 = "공석수",
             민주당 = "공석수",
             국힘_공석율 = "공석비율",
             민주_공석율 = "공석비율") |> 
  fmt_percent(columns = c(국힘_공석율, 민주_공석율), decimals = 1)  |> 
  tab_footnote(
    footnote = "나무위키: 당협위원장/목록",
    locations = cells_title(groups = "title")
  ) |> 
  tab_footnote(
    footnote = "인천 남동을(윤관석)/부평갑(이성만)/분당갑(김병관)",
    locations = cells_body(columns = 민주당, rows = 1)
  ) |> 
  tab_spanner(
    label = "국민의힘 ",
    columns = c(
      국힘_위원장수, 국민의힘, 국힘_공석율
    )
  ) |> 
  tab_spanner(
    label = "더불어민주당",
    columns = c(
      민주_위원장수, 민주당, 민주_공석율
    )
  ) |> 
  tab_style(
    style = cell_text(color = "#fc0303", weight = "bold", size = "large"),
    locations = cells_body(
      columns = c(국민의힘, 국힘_공석율), 
      rows = 권역 == "수도권"
    )) |> 
  tab_style(
    style = cell_text(color = "#fc6203", weight = "bold", size = "large"),
    locations = cells_body(
      columns = c(국민의힘, 국힘_공석율), 
      rows = 권역 == "경상권"
    )) |> 
  tab_style(
    style = cell_text(color = "blue", weight = "bold", size = "large"),
    locations = cells_body(
      columns = c(민주당, 민주_공석율), 
      rows = 권역 == "수도권"
    ))  |> 
  ## 표 전체 합계 -------------------------------------
    grand_summary_rows(
      columns = c(정수, 민주_위원장수, 국힘_위원장수, 민주당, 국민의힘),
      fns =  list(label = "합계", fn = "sum"),
      fmt = ~ fmt_integer(.),
      side = "bottom"
    )  |> 
    grand_summary_rows (
      columns = 국힘_공석율,
      fns =  list("합계" = ~grand_pcnt_func(region_district_tbl)[2]),
      fmt = ~ fmt_percent(., decimals = 1)
    ) |> 
    grand_summary_rows (
      columns = 민주_공석율,
      fns =  list("합계" = ~grand_pcnt_func(region_district_tbl)[1]),
      fmt = ~ fmt_percent(., decimals = 1)
    )  

region_district_gt
권역별 지역/당협위원장 현황1
권역 선거구수 더불어민주당 국민의힘
지역위원장수 공석수 공석비율 당협위원장수 공석수 공석비율
수도권 121 118 32 2.5% 102 19 15.7%
경상권 65 65 0 0.0% 60 5 7.7%
충청제주강원 39 39 0 0.0% 36 3 7.7%
전라권 28 28 0 0.0% 27 1 3.6%
합계 253 250 3 1.2% 225 28 11.1%
1 나무위키: 당협위원장/목록
2 인천 남동을(윤관석)/부평갑(이성만)/분당갑(김병관)
코드

# region_district_gt |>
#   gtsave("images/지역_당협위원장_권역별_공석현황.png")