5 min read

Leaflet을 이용한 서울시 Interactive Map 제작

서울시 지도 시각화를 위해 시도한 두번째 방법은 Leaflet을 사용하는 방법이다.
Leaflet은 웹 매핑 응용프로그램을 구축하는데 사용되는 오픈 소스 Javascript 라이브러리이다. 자세한 설명과 사용법은 Leaflet 웹사이트를 참조한다.

1 ‘leaflet’ 패키지 불러오기

library(leaflet)
leaflet() %>%
  addTiles()

leaflet 패키지를 이용할 경우 addTiles() 명령어 하나만으로도 Interactive한 세계 지도를 화면에 띄울 수 있다.

leaflet() %>%
  addTiles() %>%
  setView(127.001699, 37.564214, zoom = 11)

또한 setView() 명령어를 통해 중심 좌표를 서울의 위도와 경도로 설정할 경우, 서울시를 중심으로 하는 지도를 출력하는 것이 가능하다. 사실 기본적인 기능만으로도 원하는 곳의 지도를 띄우고 마커를 추가하는 등의 작업이 가능하다. 하지만 프로젝트에서는 구별 특성에 따른 단계구분도를 그리는 것을 목표로 하기 때문에 몇 가지 추가적인 과정을 거쳐야 한다.

2 대한민국 최신 행정구역 SHP 파일 다운로드

library(raster)
## Loading required package: sp
korea = shapefile('TL_SCCO_SIG.shp')
korea = spTransform(x = korea, CRSobj = CRS('+proj=longlat +datum=WGS84'))
korea = korea[1:25,]
head(korea@data)
##   SIG_CD    SIG_ENG_NM               SIG_KOR_NM
## 0  11110     Jongno-gu        \xc1\xbe\xb7α\xb8
## 1  11140       Jung-gu           \xc1\u07f1\xb8
## 2  11170    Yongsan-gu           \xbf\xeb\xbb걸
## 3  11200  Seongdong-gu \xbc\xba\xb5\xbf\xb1\xb8
## 4  11215   Gwangjin-gu \xb1\xa4\xc1\xf8\xb1\xb8
## 5  11230 Dongdaemun-gu   \xb5\xbf\xb4빮\xb1\xb8

leaflet 맵 상에서 서울시의 구별로 경계를 그리기 위해서는 addPolygons() 명령어를 사용해야 하는데, 이때 데이터 내에 polygon 정보를 포함하고 있는 SHP 파일이 필요하다. 다행히도 대한민국 최신 행정구역의 SHP 파일은 다음 사이트에서 무료로 다운로드 받을 수 있다. GIS DEVELOPER 프로젝트에서는 구별 지도를 그리는 것을 목표로 하므로 시군구를 기준으로 하는 파일을 다운로드 받으면 된다.
R에서 SHP 파일을 불러오기 위해서는 raster 패키지를 사용해야 한다. 또한 다운로드 받은 SHP 파일은 GRS80 좌표계 기준이므로 leaflet에서 사용하는 WGS84 좌표계를 기준으로 변환해야 한다. spTransform() 명령어를 통해 이를 수행할 수 있다.
우리는 서울시의 데이터만 필요하므로 1행부터 25행까지의 데이터만 사용한다.

3 서울시 구별 특성 테이블

data = read.csv('data.csv')
head(data)
##       구 SIG_CD 주유소수 등록차량수 유입교통량 유출교통량 공시지가 대학수
## 1 강남구  11680      125     235376  164634707  159410492      119      3
## 2 강동구  11740       43     143137   49936872   41439778      117      1
## 3 강북구  11305       28      76265   39214634   39113800      114      2
## 4 강서구  11500       73     204000   36895972   31378712      118      4
## 5 관악구  11620       32     119646   16043785   19963877      114      3
## 6 광진구  11215       35      99089   27095066   25629685      116      4
##   사업체수 유통업체수 주차장면적 학교수 도로면적 생활인구수 주간인구수
## 1    71373     255893     390191    120  6700039     852709    1004121
## 2    29772     114448     167853     93  3729538     496114     467542
## 3    18918      83831      89173     59  2000480     309348     284766
## 4    38524     170268     260730    138  3994520     561761     537358
## 5    26105      72107     151070     91  2607929     519174     471660
## 6    24535      99408     129859     78  2495694     408328     392245
##   야간인구수
## 1     744327
## 2     516380
## 3     326815
## 4     579028
## 5     552959
## 6     419694

데이터 수집 단계에서 만들었던 서울시 구별 특성 테이블을 불러온다. 해당 테이블은 Rhino 프로젝트 깃헙 페이지를 방문하면 다운로드 받을 수 있다.

4 데이터 병합

korea@data = sp::merge(korea@data, data)
head(korea@data)
##   SIG_CD    SIG_ENG_NM               SIG_KOR_NM       구 주유소수 등록차량수
## 1  11110     Jongno-gu        \xc1\xbe\xb7α\xb8   종로구       21      50094
## 2  11140       Jung-gu           \xc1\u07f1\xb8     중구       24      51277
## 3  11170    Yongsan-gu           \xbf\xeb\xbb걸   용산구       28      76427
## 4  11200  Seongdong-gu \xbc\xba\xb5\xbf\xb1\xb8   성동구       33     105754
## 5  11215   Gwangjin-gu \xb1\xa4\xc1\xf8\xb1\xb8   광진구       35      99089
## 6  11230 Dongdaemun-gu   \xb5\xbf\xb4빮\xb1\xb8 동대문구       46      97712
##   유입교통량 유출교통량 공시지가 대학수 사업체수 유통업체수 주차장면적 학교수
## 1   74991072   83213968      114      8    39952     133876      94485     60
## 2   81367878   83157252      114      3    60957     824458     108240     48
## 3  103556618  109186211      121      3    20813     281000     113341     47
## 4   69841974   65458213      120      3    27868      91378     121228     71
## 5   27095066   25629685      116      4    24535      99408     129859     78
## 6   23253873   28384756      117      6    31878     160875     135626     78
##   도로면적 생활인구수 주간인구수 야간인구수
## 1  2369772     339134     424302     278200
## 2  2148274     358073     463649     282562
## 3  2481085     325387     351001     306998
## 4  2256408     365824     373757     360053
## 5  2495694     408328     392245     419694
## 6  2637076     395998     394574     396899

SHP 파일은 ‘data’, ‘polygons’, ‘plotOrder’, ‘bbox’, ‘proj4string’으로 구성되어있다. 여기서 ’data’ 에 각 구의 이름과 시군구코드가 저장되어있고, ‘polygons’에 구별 위도, 경도가 저장되어있다. 지도에 나타내고 싶은 구별 특성은 ’data’에 병합하여 저장하면 된다. 이때 korea는 SHP파일이기 때문에 ’raster’ 패키지를 불러온 후 sp::merge() 명령어를 사용해야 테이블 병합이 가능하다.

5 지도 그리기

pal1 = colorBin(palette = 'Greys', domain = korea@data$학교수)

우선 단계구분을 위한 팔레트를 먼저 생성한다. 여기서는 구별 ’학교수’를 기준으로 한다.

library(leaflet.extras)
korea %>%
  leaflet() %>%
  addTiles(group = 'OSM') %>%
  addProviderTiles('CartoDB', group = 'Carto') %>%
  addProviderTiles('Esri', group = 'Esri') %>%
  setView(127.001699, 37.564214, zoom = 11) %>%
  addSearchOSM() %>%
  addResetMapButton() %>%
  addPolygons(weight = 3,
              fillOpacity = 0.8,
              fillColor = ~pal1(학교수),
              color = 'black',
              label = ~구,
              highlight = highlightOptions(weight = 3,
                                           color = 'red',
                                           bringToFront = TRUE),
              group = '학교수') %>%
  addLegend(title = '학교수', pal = pal1, values = ~학교수, opacity = 1,
            position = 'bottomright', group = '학교수') %>%
  addLayersControl(baseGroups = c('OSM', 'Carto', 'Esri'))

본격적으로 서울시 구별 특성 지도를 그려보도록 할 것이다. addTiles() 명령어만 입력하였을 때 제공되는 기본 테마 이외에도 addProviderTiles() 명령어를 사용하여 ‘CartoDB’, ‘Esri’ 등 다양한 테마를 적용할 수 있다. 또한 leaflet.extras 패키지를 불러올 시 addSearchOSM(), addResetMapButton() 등 interactive한 요소들을 추가하는 것도 가능하다.

최종 결과물을 확인하고 싶은 경우 Rhino 프로젝트 시각화 대시보드를 방문하여 ’서울시 구별 특성 지도’에서 확인할 수 있다.