국회위원선거 서울특별시 선거구 지도 만들기

R프로그래밍 언어의 ggplot2, sf 패키지 등을 이용해서 제22대 총선 선거구 지도를 그려볼까한다. 전국지도를 다 그릴수는 없고, 서울특별시만 대상으로 데이터를 가공해서 그려보았다. 디자인은 최근 여론조사들을 참고했고, 왼쪽에는 전체 서울시의 지도를, 오른쪽은 특정 선거구를 그려보았다.

데이터만들기

지도를 그리는 프로그래밍보다 관련 데이터를 가공하는 과정이 더 어렵다. 요약하자면, 아래 3개 스탭으로 진행되었다.

  1. 읍면동 지도와 선거구 데이터를 읽어온다.
  2. 지도데이터의 동이름과 선거구 동이름을 매핑하여 조인한다.
  3. 선거구 기준으로 읍면동 구획을 병합한다.

첫째로, 주소기반산업지원서비스-구역의도형 홈페이지에서 행정구역 지도를 받아야 한다. 두번째로 중앙선거관리위원회 홈페이지에서 선거구 및 읍면동현황 엑셀파일을 받아 지도데이터와 연결(JOIN)해야 한다. 선거구정보는 “창제1동, 창제2동, 숭인제1동, 숭인제2동” 이렇게 표시되는 반면에, 지도데이터는 “창1동, 창2동, 숭인1동, 숭인2동"으로 표시되어 있다. 선거구 정보에는 코드정보가 없었고, 동이름도 미묘한 차이에 지도 데이터와 매핑하기가 쉽지 않았다. 마지막으로 선거구는 행정동 여러개를 하나로 묶은 단위이기 때문에, sf 패키지를 이용해서 구역 여러개를 하나로 병합하는 과정도 필요했다.

과정이 좀 길다보니, shp 파일을 따로 만들었다. 아래 링크를 클릭해서 받을 수 있으며, UTF-8 인코딩으로 되어 있으니 윈도우 환경에서 잘 변환해서 사용하시길 바란다.

결과파일 다운로드 map_seongeogu_0_01x.zip

직접만들고 싶다면, 아래 포스팅들을 참고한다.

R프로그래밍 - ggplot 한국지도 그리기
(ggplot2) 지도에서 지역별 경계 합치기

지도 데이터

map_seongeogu_0_01x.zip 파일을 다운받았다면, RStudio에서 읽어온다.

> map_seoul = read_sf('./map_seongeogu_0_01x.shp')
> map_seoul
Simple feature collection with 49 features and 2 fields
Geometry type: POLYGON
Dimension:     XY
Bounding box:  xmin: 935292.4 ymin: 1936670 xmax: 971982.2 ymax: 1966987
Projected CRS: Korea 2000 / Unified CS
# A tibble: 49 × 3
   snggmyn  sig                                                                                        geometry
   <chr>    <chr>                                                                                 <POLYGON [m]>
 1 강남구갑 강남구 ((958593.2 1943471, 957971.5 1945129, 957625.4 1946054, 957392.5 1947055, 956577.8 194747...
 2 강남구병 강남구 ((959683.7 1942399, 959474.6 1942987, 958809.2 1942894, 958593.2 1943471, 960475.4 194421...
 3 강남구을 강남구 ((966768.7 1940878, 966171.5 1940401, 965010 1940403, 964543.3 1939745, 964200.8 1939766,...
 4 강동구갑 강동구 ((969927 1949133, 968308.5 1948336, 967690.5 1948503, 967912.3 1949095, 968301.9 1949133,...
 5 강동구을 강동구 ((968636.6 1946453, 966344.1 1947696, 966733.1 1948880, 965816.5 1949365, 965480.5 194938...
 6 강북구갑 강북구 ((959566.2 1959136, 959135.4 1958681, 958904.7 1958077, 958434.8 1959472, 957471.2 195898...
 7 강북구을 강북구 ((959566.2 1959136, 959638.1 1959111, 960267.4 1958409, 959180.9 1957159, 957832.7 195699...
 8 강서구갑 강서구 ((943318.3 1947948, 941725.6 1947669, 941197.5 1948779, 941085.4 1949378, 940589.5 195000...
 9 강서구병 강서구 ((943803.3 1948021, 943318.3 1947948, 943245.9 1948428, 942719.9 1949058, 942119.7 194895...
10 강서구을 강서구 ((939249.8 1949268, 938825.2 1949582, 938325.2 1949494, 938111.7 1948947, 937624.1 194890...
# ℹ 39 more rows
# ℹ Use `print(n = ...)` to see more rows

그 중에서 송파구 선거구만 가져온다.

> map_songpa = map_seoul |> filter(str_detect(sig, "송파구"))
> map_songpa
Simple feature collection with 3 features and 2 fields
Geometry type: POLYGON
Dimension:     XY
Bounding box:  xmin: 961781.9 ymin: 1940878 xmax: 970070.3 ymax: 1949387
Projected CRS: Korea 2000 / Unified CS
# A tibble: 3 × 3
  snggmyn  sig                                                                                        geometry
* <chr>    <chr>                                                                                 <POLYGON [m]>
1 송파구갑 송파구 ((965949.9 1944390, 965669.6 1944636, 964807.7 1945836, 963756.5 1947584, 964840.5 194864...
2 송파구병 송파구 ((966967.8 1941125, 967023.2 1941935, 966453 1943527, 965949.9 1944390, 966708.8 1945066,...
3 송파구을 송파구 ((966967.8 1941125, 966768.7 1940878, 965258.7 1943522, 964182.2 1944235, 962610.8 194484...

해당 데이터를 가지고 fill 파라메터만 정의해서 색을 입혀본다.

ggplot(map_songpa) +
  geom_sf(aes(fill = snggmyn))

scale_fill_viridis_d 를 이용해서 색을 조금 바꿔봤다. begin, end 를 적절히 사용하면 양극단의 강한색을 조금이나마 제외시킬 수 있다.

ggplot(map_songpa) +
  geom_sf(aes(fill = snggmyn)) +
  scale_fill_viridis_d(begin = 0.3, end = 0.8)

추가로 patchwork, ggplot2 패키지의 다양한 함수들을 이용하면, 아래와 같이 2개이상의 지도를 한 plot 안에 그릴 수 있다.

위에 행정동 구역을 덧그리면, 아래와 같이 표현 가능하다.

양천구 선거구 지도

중구성동구 선거구 지도

서대문구 선거구 지도


더 보면 좋을 글들