행정구 병합하기
개요
시군구 단위의 지도를 그릴 때 자치구와 행정구를 모두 포함할지 고민되는 경우가 있습니다. 경기도 수원시나 성남시처럼 행정구가 설치된 경우, 이를 병합해서 시로만 표현하는 경우가 많습니다. 이번 글에서는 행정구 경계를 병합하는 방법을 단계별로 살펴보겠습니다.
행정구역 경계 데이터 다운로드하기
우선, 지도의 기초 데이터를 준비해야 합니다. V-World 디지털트윈국토 사이트에서 필요한 공간정보 데이터를 다운받을 수 있습니다. 로그인 후 ’행정구역’을 검색해 행정구역시군구_경계 게시물에서 시군구 경계 데이터를 받을 수 있습니다. 이번에는 수도권(서울, 인천, 경기)의 데이터를 다운로드하여 사용합니다.
shp 파일 읽기 및 병합하기
파일을 처리하기 위해 tidyverse와 sf 패키지를 사용합니다. list.files 함수로 폴더 내 모든 shp 파일을 찾고, 이를 st_read 함수로 읽어 데이터프레임 형식으로 변환합니다. 이후 bind_rows를 통해 읽어들인 여러 데이터를 하나로 합칩니다. 이 과정을 통해 수도권에 해당하는 행정구역 데이터를 통합한 데이터셋을 얻을 수 있습니다.
# 패키지 로드
library(tidyverse)
library(sf)
# 데이터 불러오기
folder_path <- "데이터/수도권 지도/행정구역 경계"
shp_files <- list.files(folder_path, pattern = "*.shp$", full.names = TRUE)
merged_shp <- shp_files %>%
lapply(st_read) %>%
bind_rows()
## Reading layer `LARD_ADM_SECT_SGG_11_202405' from data source
## `C:\...\데이터\수도권 지도\행정구역 경계\LARD_ADM_SECT_SGG_11_202405.shp'
## using driver `ESRI Shapefile'
## Simple feature collection with 25 features and 4 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: 179191.4 ymin: 536562.8 xmax: 216242.3 ymax: 566863.5
## Projected CRS: Korea_2000_Korea_Central_Belt_2010
## Reading layer `LARD_ADM_SECT_SGG_28_202405' from data source
## `C:\...\데이터\수도권 지도\행정구역 경계\LARD_ADM_SECT_SGG_28_202405.shp'
## using driver `ESRI Shapefile'
## Simple feature collection with 10 features and 4 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: -10044.95 ymin: 481583 xmax: 181782.2 ymax: 600780
## Projected CRS: Korea_2000_Korea_Central_Belt_2010
## Reading layer `LARD_ADM_SECT_SGG_41_202405' from data source
## `C:\...\데이터\수도권 지도\행정구역 경계\LARD_ADM_SECT_SGG_41_202405.shp'
## using driver `ESRI Shapefile'
## Simple feature collection with 44 features and 4 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: 144789.2 ymin: 477264 xmax: 274945.2 ymax: 631207.8
## Projected CRS: Korea_2000_Korea_Central_Belt_2010
# 데이터 확인
head(merged_shp)
## Simple feature collection with 6 features and 4 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: 195102.6 ymin: 545229.7 xmax: 210189.8 ymax: 559196.5
## Projected CRS: Korea_2000_Korea_Central_Belt_2010
## ADM_SECT_C SGG_NM SGG_OID COL_ADM_SE
## 1 11110 서울특별시 종로구 11 11110
## 2 11140 서울특별시 중구 34 11140
## 3 11170 서울특별시 용산구 1 11170
## 4 11200 서울특별시 성동구 1 11200
## 5 11215 서울특별시 광진구 49 11215
## 6 11230 서울특별시 동대문구 232 11230
## geometry
## 1 MULTIPOLYGON (((197800 5590...
## 2 MULTIPOLYGON (((202072.4 55...
## 3 MULTIPOLYGON (((197569.6 55...
## 4 MULTIPOLYGON (((203845.4 55...
## 5 MULTIPOLYGON (((208984.4 55...
## 6 MULTIPOLYGON (((206279 5563...
행정구 경계 병합하기
SGG_NM 열에 포함된 지역 명칭을 변환합니다. str_replace 함수를 사용해 ’경기도 수원시 장안구’와 같은 값을 ’경기도 수원시’로 변환하고, 이후 group_by와 summarise를 통해 동일한 이름을 가진 행정구역을 병합합니다. 이 과정을 통해 행정구가 시 단위로 통합됩니다.
str_replace(SGG_NM, "(\\s\\w+)\\s\\w+$", "\\1")는 문자열에서 특정 패턴을 찾아 변환하는 함수입니다. 이 코드는 SGG_NM 열에 저장된 행정구역 이름에서 두 번째 공백 뒤의 단어를 제거하고, 앞부분만 남깁니다. 예를 들어 ’경기도 수원시 장안구’라는 값이 ’경기도 수원시’로 변환됩니다. 여기서 정규표현식 "(\\s\\w+)\\s\\w+$"는 문자열에서 첫 번째 공백과 그 뒤의 단어를 하나의 그룹으로 캡처(\\1)하며, 두 번째 공백 이후의 단어는 제거합니다.
# 패키지 로드
library(stringr)
# 행정구역 명칭의 두 번째 공백 뒤 단어를 없애기
result <- merged_shp %>%
mutate(SGG_NM = str_replace(SGG_NM, "(\\s\\w+)\\s\\w+$", "\\1")) %>%
group_by(SGG_NM, COL_ADM_SE) %>%
summarise()
# 행정구역 확인
unique(result$SGG_NM)
## [1] "경기도 가평군" "경기도 고양시" "경기도 과천시"
## [4] "경기도 광명시" "경기도 광주시" "경기도 구리시"
## [7] "경기도 군포시" "경기도 김포시" "경기도 남양주시"
## [10] "경기도 동두천시" "경기도 부천시" "경기도 성남시"
## [13] "경기도 수원시" "경기도 시흥시" "경기도 안산시"
## [16] "경기도 안성시" "경기도 안양시" "경기도 양주시"
## [19] "경기도 양평군" "경기도 여주시" "경기도 연천군"
## [22] "경기도 오산시" "경기도 용인시" "경기도 의왕시"
## [25] "경기도 의정부시" "경기도 이천시" "경기도 파주시"
## [28] "경기도 평택시" "경기도 포천시" "경기도 하남시"
## [31] "경기도 화성시" "서울특별시 강남구" "서울특별시 강동구"
## [34] "서울특별시 강북구" "서울특별시 강서구" "서울특별시 관악구"
## [37] "서울특별시 광진구" "서울특별시 구로구" "서울특별시 금천구"
## [40] "서울특별시 노원구" "서울특별시 도봉구" "서울특별시 동대문구"
## [43] "서울특별시 동작구" "서울특별시 마포구" "서울특별시 서대문구"
## [46] "서울특별시 서초구" "서울특별시 성동구" "서울특별시 성북구"
## [49] "서울특별시 송파구" "서울특별시 양천구" "서울특별시 영등포구"
## [52] "서울특별시 용산구" "서울특별시 은평구" "서울특별시 종로구"
## [55] "서울특별시 중구" "서울특별시 중랑구" "인천광역시 강화군"
## [58] "인천광역시 계양구" "인천광역시 남동구" "인천광역시 동구"
## [61] "인천광역시 미추홀구" "인천광역시 부평구" "인천광역시 서구"
## [64] "인천광역시 연수구" "인천광역시 옹진군" "인천광역시 중구"
시도 경계 만들기
시군구 데이터를 시도 단위로 더 단순화하기 위해 SGG_NM에서 첫 번째 단어를 추출하여 SIDO_NM 열을 생성합니다. 이를 위해 str_replace를 사용하며, ’경기도 수원시’에서 ’경기도’만 남도록 변환합니다. 이후 group_by와 summarise로 데이터를 병합하여 시도 단위의 데이터를 생성합니다.
# 시도 칼럼 생성 및 병합
result_sido <- result %>%
mutate(SIDO_NM = str_replace(SGG_NM, "(\\w+)\\s\\w+", "\\1")) %>%
group_by(SIDO_NM) %>%
summarise()
# 행정구역 확인
unique(result_sido$SIDO_NM)
## [1] "경기도" "서울특별시" "인천광역시"
수도권 시군구 지도 작성하기
병합된 데이터를 지도에 시각화하기 위해 ggplot2 패키지를 사용합니다. geom_sf 함수는 공간 데이터를 시각화할 수 있도록 지원합니다. 경계선 색상과 두께를 설정해 시군구와 시도의 경계를 각각 다른 레이어로 표현할 수 있습니다. theme_void를 사용해 축과 배경을 제거하여 깔끔한 지도를 만듭니다.
# 패키지 로드
library(ggplot2)
# 지도 작성
ggplot() +
geom_sf(data = result, colour = "gray40", fill = NA, linewidth = 0.5) +
geom_sf(data = result_sido, colour = "gray20", fill = NA, linewidth = 1) +
theme_void()

shp 파일 저장하기
병합된 데이터를 shp 파일로 저장해 이후 활용할 수 있도록 합니다. 이를 위해 st_write를 사용하며, UTF-8 인코딩을 설정해 한글 데이터가 깨지지 않도록 합니다. 또한, append = FALSE로 지정하여 기존 파일에 덮어쓰기할 수 있도록 설정합니다.
st_write(result,
"아웃풋/수도권 행정구 병합 지도.shp",
append = FALSE,
layer_options = "ENCODING=UTF-8")
## Deleting layer `수도권 행정구 병합 지도' using driver `ESRI Shapefile'
## Writing layer `수도권 행정구 병합 지도' to data source
## `아웃풋/수도권 행정구 병합 지도.shp' using driver `ESRI Shapefile'
## options: ENCODING=UTF-8
## Writing 66 features with 2 fields and geometry type Unknown (any).