Map visualization using sf

sf 패키지에 대한 간략한 소개 및 따릉이 역과 한강 사이의 최단거리 구하기

Author

Don Don

Published

March 9, 2024

library(sp)
library(sf)
library(tidyverse)
library(data.table)

따릉이 대여소와 한강까지의 최단거리 구하기

따릉이 관련 프로젝트 중에 서울시 따릉이 대여소와 한강까지의 최단 거리를 변수로 추가해야 하는 일이 있었다. 따릉이 정비소는 지도 상에서 point이고 한강은 수많은 점으로 이루어진 polygon 형태이므로 거리를 구하기가 쉽지 않았다. 이번 글에서는 삽질을 통해 알아낸 point와 polygon 사이의 최단거리를 구하는 방법에 대해 기술해보고자 한다.

R에는 대표적인 공간 데이터를 다루는 패키지로 sp, sf 패키지가 있다. 두 패키지에는 point와 polygon 사이의 거리를 구하는 함수가 내장되어 있는데 이번 글에서는 sf 패키지를 이용해서 따릉이 대여소와 한강까지의 최단거리를 구해본다.

따릉이 대여소 정보 데이터 불러오기

서울시 공공 자전거 대여소 정보는 https://data.seoul.go.kr/dataList/OA-13252/F/1/datasetView.do 에서 다운로드가 가능하다.

따릉이 종류에 따라 LCD, QR 방식이 있다. tutorial에서는 LCD 방식의 따릉이 데이터만 이용한다.

station <- read_csv('~/Desktop/quarto_blog/posts/data/공공자전거 대여소 정보.csv', locale = locale(encoding = 'CP949'))
colnames(station) <- c('대여소번호', '대여소명', '자치구', '상세주소', 'lat', 'long', '설치시기', 'LCD거치대수', 'QR거치대수', '운영방식')
station %>% head()
# A tibble: 6 × 10
  대여소번호 대여소명         자치구 상세주소   lat  long 설치시기   LCD거치대수
       <dbl> <chr>            <chr>  <chr>    <dbl> <dbl> <date>           <dbl>
1       2301 현대고등학교 건… 강남구 서울특…   37.5  127. 2017-06-13          10
2       2302 교보타워 버스정… 강남구 서울특…   37.5  127. 2017-06-13          10
3       2303 논현역 7번출구   강남구 서울특…   37.5  127. 2017-06-13          15
4       2304 신영 ROYAL PALA… 강남구 서울특…   37.5  127. 2017-06-13          10
5       2305 MCM 본사 직영점… 강남구 서울특…   37.5  127. 2017-06-13          10
6       2306 압구정역 2번 출… 강남구 서울특…   37.5  127. 2017-06-13          30
# ℹ 2 more variables: QR거치대수 <dbl>, 운영방식 <chr>
station_lcd <- station %>% filter(운영방식 == 'LCD') %>% select(대여소번호, 자치구, lat, long)
station_QR <- station %>% filter(운영방식 == 'QR') %>% select(대여소번호, 자치구, lat, long)

한강 데이터 불러오기

한강 데이터는 구글링하면 바로 구할 수 있다. 한강에서 뻗어나가는 하천 정보를 추가하고 싶으면 qgis에서 작업을 한 후에 shp 파일을 R로 불러오는 것이 가장 빠르다. 나는 한강 데이터에 북쪽의 법정하천을 추가해서 shp 파일을 만들었다.

NA_W <- st_read("~/Desktop/quarto_blog/posts/data/river/F006_20240120_10.shp", options="encoding=Euc-kr")
plot(NA_W, max.plot = 12)

좌표계 변환

이전에 포스팅한 바와 같이 위도, 경도의 순서를 바꾸고 좌표계 변환을 해주는 코드이다.
좌표계는 종류도 많고 복잡하기 때문에 접근하기가 쉽지 않은 것 같다. 데이터에 부여된 좌표계의 특징과 대략적인 의미만 파악해도 적용하는데는 무리가 없는 것 같다.
간략하게 현재 사용하는 좌표계의 특징을 살펴보면 다음과 같다.

  • KATEC 계열: 한반도 전체를 하나의 좌표계로 나타낼 때 많이 사용하는 좌표계
  • EPSG:5179 → UTM-K (GRS80)
  • 서비스: 네이버지도
  • CRS 스펙: +proj=tmerc +lat_0=38 +lon_0=127.5 +k=0.9996 +x_0=1000000 +y_0=2000000 +ellps=GRS80 +units=m +no_defs
temp <- station_lcd

colnames(temp)[c(3,4)] = c("Y","X")
convertCoordSystem <- function(data = temp, from.crs = from.crs, to.crs = to.crs){
  xy = data.frame(long = data$X, lat = data$Y)
  xy = as.data.frame(apply(xy, 2, as.numeric))
  
  coordinates(xy) = ~long+lat
  
  from.crs = CRS(from.crs)
  from.coordinates = SpatialPoints(xy, proj4string=from.crs)
  
  to.crs = CRS(to.crs)
  changed = as.data.frame(SpatialPoints(spTransform(from.coordinates, to.crs)))
  names(changed) = c("long", "lat")
  
  return(changed)
}
from.crs = "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"
to.crs = "+proj=tmerc +lat_0=38 +lon_0=127.5 +k=0.9996 +x_0=1000000 +y_0=2000000 +ellps=GRS80 +units=m +no_defs"
coord = convertCoordSystem(data = temp, from.crs = from.crs, to.crs = to.crs)
temp[,c(3,4)] = coord 
colnames(temp)[c(3,4)] = c("X","Y")
coordinates(temp) = ~X+Y
temp = st_as_sf(temp , coord = c("X", "Y") , crs = 5179)
st_crs(temp) = st_crs(NA_W)

따릉이 대여소와 한강 사이의 최단거리 구하기

점과 점 사이의 거리를 구하는 것은 쉽지만 한강처럼 shp파일은 데이터의 형식이 polygon이므로 최단거리를 구하기가 쉽지 않다. 그러나 R의 sf 패키지를 이용하면 쉽게 구할 수 있다. sf 패키지에 내장되어 있는 st_distance 함수를 이용하면 점과 polygon 사이의 최단거리를 구할 수 있다. by_elements = F 로 설정할 경우 거리에 대한 matrix를 반환한다.
(sp 패키지에도 비슷한 함수가 내장되어있지만 sp 패키지와 sf 패키지를 혼용해서 사용할 수 없으므로 데이터의 형태를 sp 패키지에 맞는 데이터 형태로 변환해주어야 한다)

d <- st_distance(NA_W, temp, by_element = T)
temp <- cbind(temp, d)
temp

데이터 병합

기존 데이터에 대여소 번호 기준으로 최단거리 데이터를 병합하면 최종 데이터가 완성된다.

location <- data.frame(temp)[,c(1,3)]
location <- location %>% rename(distance = d)
location %>% head()
station_lcd <- left_join(station_lcd, location, by = '대여소번호')
station_lcd$distance <- as.numeric(station_lcd$distance)
station_lcd

좌표계 설명 : https://www.osgeo.kr/17

좌표계 변환 코드 참고 : https://rpubs.com/KOOJA/coorinatesTransformationExample

Citation

BibTeX citation:
@online{don2024,
  author = {Don, Don and Don, Don},
  title = {Map Visualization Using Sf},
  date = {2024-03-09},
  url = {https://dondonkim.netlify.app/posts/2021-06-12-map-visualization-using-sf/sf.html},
  langid = {en}
}
For attribution, please cite this work as:
Don, Don, and Don Don. 2024. “Map Visualization Using Sf.” March 9, 2024. https://dondonkim.netlify.app/posts/2021-06-12-map-visualization-using-sf/sf.html.