Skip to content

bit2r/bitSpatial

Repository files navigation

bitSpatial

설치하기

bitSpatial 패키지는 GitHub으로부터 다음과 같이 설치합니다.

# install.packages("devtools")
devtools::install_github("bit2r/bitSpatial")

배경

지방자치 시대에 대한민국이 아닌 지역에 대한 경제, 사회, 문화 등의 이해는 중요한 사회과학적인 요소입니다. 그리고 지역에 대한 이해는 좀더 직관적인 시각화 방법이 유용합니다.

그러나 이러한 방법은 장미빛 청사진이 아닙니다. 데이터를 지역 기준으로 집계하고, 집계한 통계를 시각화하는 방법이 녹록치 않기 때문입니다.

1. 행정구역 체계의 일반화 이슈

현재 우리나라 행정구역 체계는 다음 그림과 같습니다. 행정 구역은 크게 1개의 특별시(서울), 6개의 광역시(부산, 대구, 인천, 광주, 대전, 울산), 6개의 도(경기, 충북, 충남, 전남, 경북, 경남), 1개의 특별자치시(세종), 3개의 특별자치도(강원, 전북, 제주)로 구성되어 있습니다.1

소스: http://nationalatlas.ngii.go.kr/pages/page_1217.php

소스:

삽화소스: 국토지리정보원 청소년을 위한 국가지집

이를 기준으로 행정구역 체계를 일반화하기 위해서 광역시도 > 시군구 > 읍면동 레벨의 3단계 계층을 생각해볼 수 있습니다.

  • 광역시도
    • 특별시 + 특별자치시 + 특별자치도 + 광역시 + 도
  • 시군구
    • 시 + 군 + 구
  • 읍면동
    • 읍 + 면 + 동

그러나 광역시도 > 시군구 > 읍면동의 3단 계층 구조에서 다음의 예외 사항이 존재합니다.

  • 세종특별 자치시의 구조
    • 2단계 계층
    • 광역시도 > 시군구 레벨 없음 > 읍면동
  • 충청남도 천안시 동남구 신방동
    • 4단계 계층
    • 도 + 시 + 구 + 읍면동
    • 인구가 팽창하는 도에 포함된 일부 시의 경우 (구) 레벨을 포함하기도 함
      • 경기도 수원시, 경기도 성남시, 경기도 고양시 등

2. 행정구역 체계의 변화 이슈

행정구역 체계는 변화합니다. 다음 그림은 광역시도 레벨의 행정구역 체계 변경 히스토리입니다.

소스: http://nationalatlas.ngii.go.kr/pages/page_1217.php

소스:

삽화소스: 국토지리정보원 청소년을 위한 국가지집

지역에 대한 통계가 현황 분석을 목적으로 한다면 문제가 없겠지만, 시점별 통계의 변화를 살피는 추이분석을 수행할 경우에는 문제가 발생합니다. 행정구역 체계의 변경으로 인해서 과거의 통계를 현재의 행정구역에 매핑할 수 없는 경우가 있습니다.

그나마 광역시도와 시군구 레벨의 행정구역의 변경은 흔치 않지만, 읍면동 레벨(특히 행정동 기준)의 행정구역의 변경은 매우 잦게 발생합니다. 하나의 동이 여러 개의 동으로 분동되거나, 여러 동이 합동하여 하나의 구로 변합되거나 하는 사례가 많습니다.

3. 법정동이냐 행정동이냐 그것이 문제로다.

광역시도 > 시군구 > 읍면동 레벨에서의 읍면동은 두 가지 기준이 있습니다.

  • 법정동
    • 으로 의 의미로, 법으로 정한 행정구역의 단위
    • 1914년 시행된 행정구역 통폐합때 정한 것으로, 현재까지 거의 변동이 없음
  • 행정동
    • 행정능률, 주민편의에 의해 설정한 행정구역의 단위
    • 인구수 기반으로 나뉘어지며 주민센터에서 관리하는 구역
    • 편의에 따라 분할/병합 등의 변경 및 폐지가 발생함

문제는 법정동:행정동의 관계는 M:N의 관계로, 통계 집계에 있어서 상호 매핑하기 어렵기 때문에 하나의 집계 기준을 가져가야 한다는 점입니다.

  • 법정동은 변동이 적기 때문에 법정동의 집계기준으로 가져가면 추이분석 등의 장점이 있지만,
    • 공공 데이터에서 법정동 기준으로 배포하는 통계가 적습니다.
  • 행정동은 변동이 많기 때문에 행정동의 집계기준으로 가져가면 추이분석 등의 단점이 있지만,
    • 공공 데이터에서 행정동 기준으로 배포하는 통계가 많습니다.
    • 많은 파생 통계가 인구통계 기반으로 작성되기 때문에 인구통계는 중요한 통계입니다.

4. 읍면동 행정구역 레벨 집계의 어려움

지번 주소에서 이제는 도로명 주소가 표준 주소 체계로 사용되고 있습니다. 그러나 우리가 집계해야할 지역기반의 Raw 데이터는 지번주소, 도로명주소가 혼용되어 있습니다. 과거의 통계를 무시하고 항상 현재 기준의 통계를 사용할 수 없으며, 경우에 따라서 현재 기준의 Raw 데이터가 과거 주소 체계로 배포되는 문제도 있습니다.

도로명 주소는 길게 이어진 도로를 기준으로 만들어진 체계입니다. 구역을 분할하는 기준이 아니어서, 어떤 도로는 여러 구역을 넘나들면 이어져 있기도합니다. 그래서 도로명 주소 정보로 행정동이나 법정동으로 집계하는 것은 그리 쉬운 작업은 아닙니다.

5. 비표준화된 관리 체계

정부에서 제공하는 공공 데이터는 한심스럽게도, 이러한 지역 체계의 표준이 없습니다. 일례로 행정안전부에서 관리하는 행정동 코드와 통계청에서 관리하는 행정동 코드 체계가 다릅니다. 그로므로 여러 공공 데이터를 통합하여 데이터를 분석할 때에는 데이터 수요자가 이 문제를 해결해야 합니다.

6. 공공재로서의 수치지도의 한계

지리정보는 국가분단이라는 안보의 특수성이 있기 때문에 중요하게 다뤄야하는 기밀일 수 있습니다. 그러나 행정구역 경계 수치지도의 경우에는 이와 무관한 정보로서 민간 및 학계의 연구를 위해서 안정적으로 공급되어야 합니다. 그러나 정부의나 공공 기관에서 배포하는 행정구역 경계 수치지도는 거의 제한적이고, 오류가 포함되어 있거나 행정구역 체계의 변화를 담지 못하고 있는 실정입니다. 변화하는 행정 구역체계에 따라 히스토리컬하게 배포하지 않습니다.

개요

bitSpatial은 통계지리정보(SGI; Statistical Geographic Information)를 개발을 지원하는 패키지로 광역시도 > 시군구 > 읍면동 레벨의 행정구역 경계 수치지도 기반으로 공공데이터를 집계하고, 이를 시각화하는 일련의 리소스를 제공합니다.

bitSpatial는 앞에서 제기한 이슈를 완벽하게 해결한 완벽한 솔루션은 아닙니다. 그러나 차선의 솔루션은 될 수 있습니다. 현재와 근접한 행정동 기준의 행정구역 경계 수치지도를 준비하였고, 여러 통계를 집적했습니다. 그리고 앞으로도 여러 통계를 추가해 나가려 합니다.

제공하는 리소스

통계지리정보 생산을 위한 리소스

  • 광역시도 > 시군구 > 읍면동 레벨의 행정구역 경계 수치지도 제공
    • 수치지도를 sf 객체로 가공하여 제공
      • 매년 6월 기준으로 배포
    • 17 광역시도
    • 250 시군구
    • 3,528 읍면동
  • 수치지도와 결합한 행정구역별로 집계된 통계
    • 40개 통계
    • 인구통계, 초중고 학교 통계, 병원/약국 통계
    • 집계 통계는 계속 추가할 예정
  • 수치지도와 조인할 수 있는 집계된 통계
    • 성별/연령대별 인구수
  • 수치지도와 조인할 수 있는 위치정보 데이터
    • 초중등학교 위치 데이터
    • 약국/병원 위치 데이터
    • 상가 위치 데이터

지리 기반 연산을 위한 기능

  • 위치 좌표 기반 연산
    • 두 좌표의 거리 구하기
    • 경위도 좌표계 위치정보의 좌표계 변환
  • 지리기반 집계를 위한 메타
    • 우편번호 행정동 매핑 데이터
    • 위도/경도로 행정구역 코드와 이름 가져오기

SGI 시각화를 위한 기능

  • 주제도 시각화
  • 최적 지도 이미지 사이즈 계산
  • map 시각화용 ggplot2 테마

리소스의 원천

주제도 그리기

sf 객체를 다룰 수 있는 R 사용자는 sf 객체로 제공하는 수치지도 정보와 데이터를 활용할 수 있겠으나, 익숙치 않는 사용자는 주제도 시각화 함수인 thematic_map() 함수를 사용하면 주제도를 그릴 수 있습니다.

이 함수의 원형은 다음과 같습니다.

thematic_map(
  zoom = c("mega", "cty", "admi")[1],
  subset = NULL,
  stat = NULL,
  polygon = TRUE,
  point = FALSE,
  label = NULL,
  col_cnt = 9,
  palette = "YlOrRd",
  line_col = "darkgray",
  fill = "lightblue",
  point_col = "blue",
  title = NULL,
  subtitle = NULL,
  legend_pos = c("none", "right", "left", "bottom", "top"),
  base_family = "NanumSquare"
)

줌 레벨별 시각화

광역시도 > 시군구 > 읍면동의 3단계 줌 레벨을 지원합니다.

zoom 인수로 줌 레벨을 지원합니다. 기본값인 mega가 광역시도 레벨이며, cty, admi 인수값으로 시군구, 읍면동 레벨의 주제도를 그릴 수 있습니다.

광역시도별 인구분포

library(bitSpatial)

thematic_map(stat = "인구수", 
             title = "광역시도별 인구분포 현황",
             legend_pos = "right")

시군구별 병원수 현황

thematic_map(zoom = "cty",
             stat = "병원수", 
             title = "시군구별 병원수 현황",
             palette = "Blues")

특정 영역을 선택하려면 `subset` 인수를 사용합니다. 이 인수는 결과값이 logical인 R 표현식을 지원합니다.

다음은 수도원의 병원수 분포를 시각화합니다.

thematic_map(zoom = "cty",
             stat = "병원수", 
             subset = mega_nm %in% c("서울특별시", "경기도", "인천광역시"),
             title = "시군구별 병원수 현황",
             subtitle = "수도권 지역 (서울특별시, 경기도, 인천광역시)",
             palette = "Blues")

읍면동별 평균연령 현황

다음은 서울 양천구의 행정동별 평균연령 현황입니다. 양천구의 기하학적 모습이 마치 강아지와 닯았습니다.

thematic_map(zoom = "admi", 
             subset = mega_nm == "서울특별시" & cty_nm %in% "양천구", 
             stat = "age_mean", 
             label = "name",
             title = "서울 양천구 인구통계 주제도",
             subtitle = "동별 평균 연령 현황", 
             palette = "Purples",
             legend_pos = "right")

기하학적 표현

기하학적으로 통계를 표현하는 방법은 3가지로 각각의 인수로 표현이 가능합니다. 한 주제도에 세 가지 모두 표현이 가능하지만 가독성이 떨어져서 한 가지만 표현하는 것을 권장합니다.

  • 다각형의 그라데이션 색상
    • polygon
    • TRUE/FALSE로 지정
    • 기본값은 TRUE
  • 다각형 중심의 포인트 크기
    • point
    • TRUE/FALSE로 지정
    • 기본값은 FALSE
  • 다각형 중심에 숫자 라벨 표현
    • label
    • NULL은 미표현
    • “name”
      • 행정구역 이름
    • “value”
      • 통계 수치
    • 기본값은 NULL
thematic_map(zoom = "admi",
             subset = cty_nm %in% "노원구",
             stat = "household", 
             polygon = FALSE, 
             point = TRUE, point_col = "Red",
             label = "name",
             line_col = "black", fill = "grey90",
             title = "서울특별시 가구 분포",
             subtitle = "노원구 동별 가구현황")

제공하는 정보

집계된 통계

stats_info에 패키지에서 제공하는 집계된 통계 현황이 있습니다. 통계 아이디와 이름이 있는데 모두 thematic_map() 함수에서 주제도를 그릴 때 통계 정보를 식별할 수 있는 stat 인수에 사용 가능합니다.

stats_info |> 
  gt::gt() |> 
  gt::as_raw_html()
stats_id stats_nm is_use
land_area 면적 TRUE
population 인구수 TRUE
household 가구수 TRUE
pop_per_hosue 가구당인구수 TRUE
pop_male 남성인구수 TRUE
pop_female 여성인구수 TRUE
male_per_female 여성대비남성인구 TRUE
age_mean_male 남성평균연령 TRUE
age_mean_female 여성평균연령 TRUE
age_mean 평균연령 TRUE
elemnt_schl_cnt 초등학교수 TRUE
mdle_schl_cnt 중학교수 TRUE
high_schl_cnt 고등학교수 TRUE
pharmacy_cnt 약국수 TRUE
total_hospital_cnt 총의료기관수 TRUE
doctor_cnt 총의사수 TRUE
hospital_cnt 병원수 TRUE
pubhealth_center_cnt 보건소수 TRUE
pubhealth_branch_cnt 보건지소수 TRUE
pubhealth_clinic_cnt 보건진료소수 TRUE
tertiary_hospital_cnt 상급종합병원수 TRUE
nursing_hospital_cnt 요양병원수 TRUE
clinic_cnt 의원수 TRUE
mental_hospital_cnt 정신병원수 TRUE
midwife_hospital_cnt 조산원수 TRUE
general_hospital_cnt 종합병원수 TRUE
dental_hospital_cnt 치과병원수 TRUE
dental_clinic_cnt 치과의원수 TRUE
kmedicine_hospital_cnt 한방병원수 TRUE
kmedicine_clinic_cnt 한의원수 TRUE
store_cnt_retail 소매업체수 TRUE
store_cnt_acomodt 숙박업체수 TRUE
store_cnt_food 음식업체수 TRUE
store_cnt_estate 부동산업체수 TRUE
store_cnt_tech 기술업체수 TRUE
store_cnt_lease 관리임대업체수 TRUE
store_cnt_edu 교육서비스업체수 TRUE
store_cnt_medical 보건의료업체수 TRUE
store_cnt_leisure 스포츠여가업체수 TRUE
store_cnt_service 개인서비스업체수 TRUE

위치 데이터

현재는 다음과 같은 위치 데이터를 제공합니다.

  • 초중고등학교 위치정보
  • 약국 위치정보
  • 병원 위치정보
  • 상가 위치정보

주제도에 위치정보 병합

위치 데이터인 학교위치, 약국위치, 병원위치를 주제도에 매시업하여 시각화가 가능합니다.

pos_school <- school |>  
  filter(mega_nm %in% "서울특별시") |> 
  filter(school_class %in% "초등학교") |> 
  st_as_sf(coords = c("lon", "lat"), crs = 4326)

ggplot() +
  stat_density_2d(data = pos_school, 
                  mapping = aes(x = purrr::map_dbl(geometry, ~.[1]),
                                y = purrr::map_dbl(geometry, ~.[2]),
                                fill = after_stat(density)),
                  geom = 'tile',
                  contour = FALSE,
                  alpha = 0.7) +
  scale_fill_viridis_c(option = "viridis", direction = -1) +
  geom_sf(data = cty |> 
            filter(mega_nm %in% "서울특별시"),
          color = "grey30", fill = NA, linewidth = 0.8) +
  geom_sf(data = pos_school, color = "blue", size = 0.5) +  
  xlim(126.75, 127.22) + 
  ylim(37.42, 37.71) + 
  labs(title = "서울특별시 초등학교 분포 현황",
       subtitle = "출처: 공공데이터포털의 전국 초중등학교 위치 표준데이터") +
  theme_custom_map()

Footnotes

  1. http://nationalatlas.ngii.go.kr/

About

Spatial analytics resources for Korean region

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages