1 ggmap 환경설정 1

Google API는 무료가 아니다. 구글 지도 API를 사용하려면 먼저 Google Maps Pltaform - Get API Key를 참조하여 Google Maps Platform 사용 설정을 따라야만 된다. 신용카드도 등록하고 구글이 원하는 바를 모두 맞춰주면 API키가 발급된다. 월기준 40,000 호출횟수까지는 무료라고 한다. 그 이상을 넘어가면 호출 횟수당 0.005달러가 신용카드를 통해 청구된다. 따라서 API키가 외부에 노출되지 않도록 보안에 특별히 신경을 쓴다.

API키를 발급받게 받아 다음 명령어를 실행시키면 C:/Users/user/Documents/.Renviron 파일에… GGMAP_GOOGLE_API_KEY=API키 행이 추가된다. 따라서 다음부터는 자동으로 구글 지도 API를 사용할 수 있는 효과를 얻게 된다.

  • register_google(key = "API키", write = TRUE)

만약 usethis::edit_r_environ()을 사용하는 경우 GGMAP_GOOGLE_API_KEY=API키 행을 직접 추가해도 무방하다. 그리고 추천하는 것은 Maps Static API 서비스를 제외한 나머지 서비스를 모두 비활성화(Disable) 시킨다. 설사 API키가 외부에 유출되더라도 피해를 최소화할 수 있다. 그리고 필요한 경우만 API를 활성화해서 사용한다. 예를 들어 Geocoding API를 사용해야만, 주소정보를 전달했을 때 위도와 경도 정보를 반환받아 시각화할 수 있게 된다.

Google API 가격관련 자세한 사항은 다음 웹사이트를 참조한다.

library(tidyverse)
library(ggmap)

# register_google(key = "API키", write = TRUE)

2 ggmap 헬로월드

ggmap 팩키지 geocode() 함수에 주소를 던지게 되면 위경도를 반환하게 된다. 이를 get_map() 함수에 적당한 zoom = 13 를 조절하게 되면 ggmap() 함수를 통해 경기도 수원시 경기도청이 위치한 곳의 지도를 받아낼 수 있다.

(gg_locations <- c("경기도 수원시 팔달구 효원로 1 (매산로3가)") %>%
    geocode())
# A tibble: 1 x 2
    lon   lat
  <dbl> <dbl>
1  127.  37.3
gg_map <- get_map(gg_locations, zoom = 13, scale = 1)

ggmap(gg_map)

3 공공기관 지리정보 시각화

3.1 공공기관 주소 데이터

공공데이터포털, 일선행정기관 주소와 전화번호를 엑셀로 다운로드 받아 저장한 후에 readxl 팩키지로 불러와서 가장 먼저 나온 검찰이 65개로 적절한 숫자라 판단되어 주소 정보를 위도와 경도 정보로 바꾼 후에 시각화하는 사례를 실습해본다.

library(readxl)
addr_dat <- read_excel("data/일선_행정기관_주소__전화번호_2018년_11월_30일_기준_-최종.xlsx", sheet='Sheet')

addr_dat %>% 
  count(`유형_1`)
# A tibble: 11 x 2
   유형_1     n
   <chr>  <int>
 1 검찰      65
 2 경찰    2289
 3 고용     158
 4 관세      56
 5 국세     150
 6 법무     196
 7 법원     338
 8 병무      17
 9 보훈      42
10 우정    2590
11 지자체  6748

3.2 검찰주소 → 위경도

일선행정기관 주소와 전화번호에서 “도로명주소”를 추출하여 geocode() 함수로 던져 위경도주소를 받아낸다.

names(addr_dat)  <- c("기관코드", "유형_1", "유형_2", "대표기관명", "전체기관명", 
"최하위기관명", "대표전화번호", "새우편번호", "도로명주소", "비고")

addr_df <- addr_dat %>% 
  select(-`비고`) %>% 
  filter(`유형_1` == "검찰") %>% 
  mutate(`시도명` = str_extract(`도로명주소`, pattern="^([\\w]+)"))

# addr_lonlat_df <- geocode(addr_df$도로명주소)

addr_df <- bind_cols(addr_df, addr_lonlat_df)

addr_df %>% write_rds('data/addr_df.rds')

3.3 위경도 → 시각화

위경도 정보를 ggmap() 함수로 시작화한다. 이를 위해서 먼저 대한민국 중심점을 찾아 get_map()zoom = 7을 조정하여 지도를 가져온다. 그리고 나서 앞서 가져온 위경도 데이터를 지도위에 ggmap() 함수로 표식한다.

addr_df  <- read_rds('data/addr_df.rds')

## 대한민국 중심 조정
korea_lonlat <- c(lon = 128.0347222, lat = 36.15138889)
korea_map <- get_map(korea_lonlat, zoom = 7, scale = 1)

ggmap(korea_map) +
  geom_point(aes(lon, lat, color="red"), data = addr_df)

3.4 도별 위치정보 facet

ggplotfacet_wrap() 기능을 사용하고자 할 경우, base_layerggplot()을 지정하면 작은 창을 분리시켜 핵심정보만 지도상에 표식할 수 있다. 가장 검찰 주소지를 많이 갖고 있는 시도를 상위 3개 추출하여 facet 기능을 도입하여 시각화한다.

addr_df %>% 
  mutate(`시도명` = str_extract(`도로명주소`, pattern="^([\\w]+)")) %>% 
  count(`시도명`, sort=TRUE)
# A tibble: 16 x 2
   시도명             n
   <chr>          <int>
 1 경기도             9
 2 경상북도           7
 3 서울특별시         7
 4 경상남도           6
 5 강원도             5
 6 충청남도           5
 7 부산광역시         4
 8 전라남도           4
 9 전라북도           4
10 충청북도           4
11 대구광역시         3
12 광주광역시         2
13 대전광역시         2
14 울산광역시         1
15 인천광역시         1
16 제주특별자치도     1
ggmap(korea_map,
      base_layer = ggplot(aes(lon, lat), data = addr_df %>% filter(str_detect(`도로명주소`, "경기|경상북도|서울")))) +
    geom_point(aes(color = 'red')) +
    facet_wrap(~`시도명`) +
    guides(color=FALSE)

3.5 인터랙티브 시각화

인터랙티브 시각화를 위해서 leaflet 팩키지를 많이 사용한다. addProviderTiles(providers$OpenStreetMap) 인자를 명시하여 가져올 지도를 명시하고, addMarkers() 함수에 지명을 보완하는 정보를 시각화할 수 있도록 popup =을 HTML 코드로 작성한다.

library(leaflet)

leaflet(data = addr_df) %>% 
  addProviderTiles(providers$OpenStreetMap) %>% 
  addMarkers(lng=~lon, lat=~lat, clusterOptions = markerClusterOptions(),
                   popup = ~ as.character(paste0("<strong>", paste0(`유형_1`,":",`기관코드`), "</strong><br>",
                                                 "-----------------------------------------------------------<br>",
                                                 "&middot; 검찰기관명: ", `최하위기관명`, "<br>",
                                                 "&middot; 전화번호: ", `대표전화번호`, "<br>",
                                                 "&middot; 새우편번호: ", `새우편번호`, "<br>",
                                                 "&middot; 도로명 주소: ", `도로명주소`, "<br>"
                   ))) 

4 우편번호 지리정보 - 3년전 코드

대한민국 우편번호를 행정표준코드관리시스템에 접속해서 다운로드 한 후 데이터 정제과정을 통해 지리정보 시각화를 위한 데이터 품질을 높인다. 그리고 나서 지리정보를 표식하는 가장 기본적인 작업흐름을 숙지해보자.

행정표준코드관리시스템에서 우편번호를 다운로드 받는 경우 6자리 이전 우편번호를 습득하게 된다. 최신 5자리 우편번호는 인터넷 우체국 웹사이트에서 다운로드 받을 수 있다. 물론 2015.06.25일 기준 6 자리 구 우편번호도 함께 다운로드 가능하다.

우편번호가 담긴 데이터를 입수했다면, 다음 단계로 지리정보 시각화를 하려는 목표 데이터의 우편번호를 결합한다. 지리정보 시각화 데이터에 우편번호와 함께 주소정보가 있을 수 있으나, 정확하지 않을 수 있어 데이터 정제 차원에서 인터넷 우체국에서 다운로드 받은 정보와 결합을 추천한다. dplyr 팩키지 left_join() 함수에 데이터를 병합하는데 키로 우편번호를 사용한다.

지리정보 시각화를 위한 데이터에 주소정보가 결합되면, 다음 단계로 깨끗한 주소정보를 ggmap 팩키지 geocode() 함수에 던져 위도와 경도 정보를 받아온 것이 기존 표준방식이었는데 구글이 공간정보서비스에 대해서 유료화 방침을 천명한 이후 새로운 대안을 찾는 움직임이 활발하다.

위도, 경도 정보가 깨끗한 주소정보와 함께 결합되면 leaflet 팩키지 지리정보시각화 함수를 사용하여 시각화한다. 단순히 지리정보를 표식하여 지도에 찍고, 특정 표식을 클릭하게 되면 주소를 표식한다. 경기도 성남시 지역 10곳을 무작위로 뽑아 우편번호 정보를 이용하여 지도에 표식한다.

지리정보 시각화

사전준비 사항

  • 해당 우편번호가 담긴 데이터 : 예전 6자리 우편번호 혹은 최신 5자리 우편번호
  • 우편번호 데이터 인코딩 현황 확인 : 윈도우 환경이라면 신경쓸 것 없다.
    • 맥 혹은 리눅스를 사용하거나, utf-8을 기본 인코딩으로 사용하는 경우 인코딩을 일치시킨다.
    • CP949, EUC-KR로 되어있는 경우 utf-8으로 변경한다.
    • RStudio 및 Hadley Wickham이 작성한 대부분의 팩키지는 utf-8을 기본 인코딩으로 사용한다.
    • PC 플랫폼이 아닌 웹기반으로 작업하는 경우 utf-8으로 인코딩 표준을 준수한다.
##==========================================================================
## 팩키지 및 우편번호 데이터 불러오기
##==========================================================================
library(readr); library(dplyr); library(readxl); library(ggmap); library(leaflet)
setwd("~/Dropbox/01_data_science") # 윈도우

# 우편번호 코드 (5자리)
post.nrd <- read_delim("kor-map/우편번호-5자리-경기도.txt", delim="|")
names(post.nrd) <- paste0("v",seq(1,26,1))
post.nrd <- post.nrd %>% select(v1,v2,v4,v6,v9) %>%
  rename(post_code=v1,sido=v2, sigungu=v4, emd=v6, gil=v9) %>%
  mutate(addr=paste(sido,sigungu,gil)) %>%
  select(post_code, addr)
post.nrd

# 성남지역 무작위 10
gongbo.rd <- read_excel("/data/random_100.xlsx", sheet="성남지역")
names(gongbo.rd) <- c("dong","name","post_code","addr1","addr2")
gongbo.rd

# 데이터 자료형 일치 (문자형으로 통일)
post.nrd$post_code <- sapply(post.nrd$post_code, as.character)

addr.dt <- left_join(gongbo.rd, post.nrd, by="post_code")
addr.dt

##==========================================================================
## 우편번호 --> 주소 --> 위도경도 (geocode)
##==========================================================================

addr.lonlat <- addr.dt %>% select(post_code, addr)

geo.lonlat <- geocode(enc2utf8(addr.lonlat$addr), source='google', output="latlona")

addr.mst <- bind_cols(addr.lonlat,geo.lonlat)
addr.mst

##==========================================================================
## 지리정보 시각화 leaflet
##==========================================================================

leaflet(data = addr.mst) %>% addTiles() %>%
  addMarkers(~lon, ~lat, popup = ~as.character(addr))

leaflet 팩키지는 R에서 지리정보 시각화를 위한 자바스크립트를 사용할 수 있도록 만들어졌다. 따라서 웹에서 자바스크립트로 코드 몇줄로 간단히 구현한 효과를 볼 수 있다.

분당 장소 표식 10곳