1 제21대 국회의원 데이터1

1.1 * 위키백과 지역구

위키백과 대한민국_제21대_국회의원에서 지역구 의원정보를 가져온다. 비례의원정보는 없기 때문에 나중에 보정작업을 한다.

# 0. 환경설정 -----
library(httr)
library(rvest)
library(tidyverse)

# 1. 국회의원 명단 -----
## 1.1. 긁어오기 -----
Sys.setlocale("LC_ALL", "C")

url <- "https://ko.wikipedia.org/wiki/대한민국_제21대_국회의원_목록_(지역구별)"

cm_list <- vector("list", length=19)

for(idx in 1:17) {
  cm_list[[idx]] <- url %>% 
    read_html() %>% 
    html_node(xpath = glue::glue('//*[@id="mw-content-text"]/div/table[{idx+1}]')) %>% 
    html_table(fill=TRUE) %>% 
    as_tibble()
}

Sys.setlocale("LC_ALL", "Korean")

for(idx in 1:17) {
  cm_list[[idx]] <- cm_list[[idx]] %>% 
    filter(str_detect(성명, pattern = "[가-힣]{2,4}"))
}

## 1.2. 시도별 국회의원 정보 -----
cm_list <- cm_list[1:17] 

sido_name <- c("서울특별시","부산광역시","대구광역시","인천광역시","광주광역시","대전광역시","울산광역시","세종특별자치시","경기도","강원도","충청북도","충청남도","전라북도","전라남도","경상북도","경상남도", "제주특별자치도")

names(cm_list) <- sido_name

## 2.3. 리스트 --> 데이터프레임 -----

name_v <- map(cm_list, "성명") %>% flatten %>% unlist %>% as.character()
precinct_v <- map(cm_list, "선거구명") %>% flatten %>% unlist %>% as.character()
party_v <- map(cm_list, "소속 정당") %>% flatten %>% unlist %>% as.character()
geo_v <- map(cm_list, "관할구역") %>% flatten %>% unlist %>% as.character()
num_v <- map(cm_list, "선수") %>% flatten %>% unlist %>% as.numeric()

cm_df <- tibble(시도   = rep(sido_name, map_int(cm_list, nrow)),
                선거구 = precinct_v,
                이름   = name_v, 
                정당   = party_v,
                지역   = geo_v,
                선수   = num_v)

# fs::dir_create("data/congressman")
# 
# cm_df %>%
#   write_rds("data/congressman/cm_df.rds")

# listviewer::jsonedit(cm_list)

위키백과 사전에서 크롤링한 데이터를 바탕으로 스키마를 확인한다.

cm_tbl <- 
  read_rds("data/congressman/cm_df.rds")

DT::datatable(cm_tbl)

1.2 * 국회의원 국회DB

자료출처: 제21대 국회의원 검색

library(readxl)

electorates_raw <- read_excel("data/제21대_지역구.xlsx")

electorates_tbl <- electorates_raw %>% 
  mutate(시도명 = str_sub(지역, start =1, end =2))

proportion_raw <- read_excel("data/제21대_비례의원.xlsx")

proportion_tbl <- proportion_raw %>% 
  mutate(시도명 = str_sub(지역, start =1, end =2))

congressman <- bind_rows(proportion_tbl, electorates_tbl) %>% 
  select(-번호) %>% 
  mutate(소속위원회 = str_remove(소속위원회, "위원회"))

congressman %>% 
  DT::datatable()

2 통합데이터 EDA

2.1 * 소속정당

congressman %>% 
  count(정당, sort =TRUE) %>% 
  mutate(pcnt = n/ sum(n) * 100)
# A tibble: 8 x 3
  정당             n   pcnt
  <chr>        <int>  <dbl>
1 더불어민주당   169 57.3  
2 국민의힘       103 34.9  
3 무소속           9  3.05 
4 정의당           6  2.03 
5 국민의당         3  1.02 
6 열린민주당       3  1.02 
7 기본소득당       1  0.339
8 시대전환         1  0.339

2.2 * 시도명/비례

congressman %>% 
  count(시도명, sort =TRUE) %>% 
  mutate(pcnt = n/ sum(n) * 100)
# A tibble: 18 x 3
   시도명     n   pcnt
   <chr>  <int>  <dbl>
 1 경기      58 19.7  
 2 비례      47 15.9  
 3 서울      47 15.9  
 4 부산      18  6.10 
 5 경남      16  5.42 
 6 경북      13  4.41 
 7 인천      13  4.41 
 8 대구      11  3.73 
 9 충남      11  3.73 
10 전남      10  3.39 
11 전북      10  3.39 
12 강원       8  2.71 
13 광주       8  2.71 
14 대전       7  2.37 
15 충북       7  2.37 
16 울산       6  2.03 
17 제주       3  1.02 
18 세종       2  0.678

2.3 * 소속위원회

congressman %>% 
  count(소속위원회, sort =TRUE) %>% 
  mutate(pcnt = n/ sum(n) * 100)
# A tibble: 14 x 3
   소속위원회                   n  pcnt
   <chr>                    <int> <dbl>
 1 국토교통                    29  9.83
 2 산업통상자원중소벤처기업    29  9.83
 3 기획재정                    25  8.47
 4 보건복지                    24  8.14
 5 정무                        24  8.14
 6 행정안전                    22  7.46
 7 외교통일                    21  7.12
 8 과학기술정보방송통신        20  6.78
 9 농림축산식품해양수산        19  6.44
10 법제사법                    18  6.10
11 국방                        17  5.76
12 문화체육관광                16  5.42
13 환경노동                    16  5.42
14 교육                        15  5.08

2.4 * 당선방법

congressman %>% 
  count(당선방법, sort =TRUE) %>% 
  mutate(pcnt = n/ sum(n) * 100)
# A tibble: 2 x 3
  당선방법     n  pcnt
  <chr>    <int> <dbl>
1 지역구     248  84.1
2 비례대표    47  15.9

2.5 * 당선횟수

congressman %>% 
  count(당선횟수, sort =TRUE) %>% 
  mutate(pcnt = n/ sum(n) * 100)
# A tibble: 6 x 3
  당선횟수     n   pcnt
  <chr>    <int>  <dbl>
1 초선       149 50.5  
2 재선        72 24.4  
3 3선         42 14.2  
4 4선         19  6.44 
5 5선         12  4.07 
6 6선          1  0.339

2.6 * 성별

congressman %>% 
  count(성별, sort =TRUE) %>% 
  mutate(pcnt = n/ sum(n) * 100)
# A tibble: 2 x 3
  성별      n  pcnt
  <chr> <int> <dbl>
1 남      240  81.4
2 여       55  18.6

3 데이터 통합

위키백과에 나온 선거구가 담긴 데이터와 국회의원 기본정보가 담긴 국회DB 내용을 결합시켜 국회의원 마스터 DB를 제작한다.

## 국회 DB -----------------------
excel_tbl <- congressman %>% 
  mutate(id = glue::glue("{의원명}_{정당}")) %>% 
  select(id, everything())

## 위키 DB -----------------------
wiki_tbl <- cm_tbl %>% 
  rename(의원명 = 이름,
         지역구명 = 지역) %>% 
  mutate(id = glue::glue("{의원명}_{정당}")) %>% 
  select(-정당, -의원명)

## 의원 DB -----------------------
congressman_tbl <- left_join(excel_tbl, wiki_tbl, by = "id")

congressman_tbl %>% 
  filter(str_detect(당선방법, "지역"),
         is.na(시도))

congressman_tbl %>% 
  write_rds("data/congressman/congressman_21_master.rds")
library(reactable)
congressman_tbl <- 
  read_rds("data/congressman/congressman_21_master.rds")

congressman_tbl %>% 
  select(-id, -대수, -지역, -선수, - 당선방법) %>% 
  arrange(desc(시도명)) %>% 
  reactable::reactable(
      searchable = TRUE,
      # groupBy = "시도명",
      defaultColDef = colDef(
        header = function(value) gsub(".", " ", value, fixed = TRUE),
        cell = function(value) format(value, nsmall = 1),
        align = "center",
        minWidth = 30,
        headerStyle = list(background = "#f7f7f8")
      ),
      columns = list(
        소속위원회 = colDef(minWidth = 50),
        지역구명 = colDef(minWidth = 100)
      ),
      bordered = TRUE,
      highlight = TRUE
)
 

데이터 과학자 이광춘 저작

kwangchun.lee.7@gmail.com