Python으로 하는 H3 공간 분석
I. H3 란 무엇인가?
그리드 시스템(Grid System)은 일반적으로 수직과 수평으로 면, 공간을 분할하는 것을 의미하며 공간 분석의 가장 기초입니다. 우리가 발을 딛고 사는 지구는 둥근 구형체입니다. 때문에 다각형을 사용하여 지구를 균등하게 나누는 것은 불가능하다고 볼 수 있습니다. 연구자들은 다양한 방법으로 이전 세대 그리드 시스템의 한계를 극복하는 새로운 시스템을 개발하고 있는데, H3는 우버에서 공개한 육각형의 그리드 시스템입니다.
육각형의 그리드 시스템의 가장 큰 장점은 인접하고 있는 셀로 이동할 때 어떠한 방향과 각도로 이동하든 각 중심점까지의 거리가 동일하다는 점입니다.
다만 육각형의 그리드 시스템 역시 지구를 완벽히 균등하게 나누는 것은 불가능하며 몇 개의 오각형을 함께 사용해야 합니다. 다행히 지구에서 우리가 관심갖는 지역은 땅 위이기 때문에 우버는 이러한 오각형들을 바다 위에 배치하여 한계를 극복하고자 했습니다.
- H3에 대한 자세한 설명은 링크(https://eng.uber.com/h3/) 를 참고하시기 바랍니다.
II. Python으로 H3 다루기
우버의 H3 는 javascript 으로 짜여졌습니만 파이썬에서도 사용가능하도록 라이브러리가 나와 있습니다. (https://pypi.org/project/h3/)
1. 패키지 설치하기
2. 주요한 기초 메소드 및 자료형
파이썬의 h3 패키지가 좋은점은 변환된 h3 출력에 다양한 자료형을 지원한다는 점입니다. 기본 출력은 str과 list/set 이며 정수형과 numpy, memoryview를 지원합니다.
import h3 # 기본 출력으로 h3.api.basic_str 와 동일하며 str 과 list/set 출력
import h3.api.basic_int as h3_int # int와 list/set 출력
import h3.api.numpy_int as h3_np # uint64 와 ndarray 출력
import h3.api.memview_int as h3_mv # uint64 와 memoryview(colletions) 출력
from shapely.geometry import Point, Polygon
from geopy.distance import distance
import geopandas as gpd
import folium
import pandas as pd
hongdae_lat = 37.557435
hongdae_lng = 126.925808
print("홍대를 H3 7 Level로 출력합니다.\n")
print("basic_str 사용 : ", h3.geo_to_h3(hongdae_lat, hongdae_lng, 7))
print("basic_int 사용 : ", h3_int.geo_to_h3(hongdae_lat, hongdae_lng, 7))
print("numpy_int 사용 : ", h3_np.geo_to_h3(hongdae_lat, hongdae_lng, 7))
print("memview_int 사용 : ", h3_mv.geo_to_h3(hongdae_lat, hongdae_lng, 7))
print("\n홍대 H3 7 level의 1 k-ring을 출력합니다.\n")
print("basic_str 출력 결과", "\n 타입 : ", type(h3.hex_ring(h3.geo_to_h3(hongdae_lat, hongdae_lng, 7),1)), "\n 결과 : ", h3.hex_ring(h3.geo_to_h3(hongdae_lat, hongdae_lng, 7),1))
print("numpy_int 출력 결과", "\n 타입 : ", type(h3_np.hex_ring(h3_np.geo_to_h3(hongdae_lat, hongdae_lng, 7),1)), "\n 결과 : ", h3_np.hex_ring(h3_np.geo_to_h3(hongdae_lat, hongdae_lng, 7),1))
print("memview_int 출력 결과", "\n 타입 : ", type(h3_mv.hex_ring(h3_mv.geo_to_h3(hongdae_lat, hongdae_lng, 7),1)), "\n 결과 : ", h3_mv.hex_ring(h3_mv.geo_to_h3(hongdae_lat, hongdae_lng, 7),1))
A. geo_to_h3
h3.geo_to_h3(lat, lng, resolution)
는 좌표계 -> H3로 변환시켜주는 메소드로 변환하고자 하는 좌표값과 H3 크기를 인수로 받음
B. h3_to_geo
h3.h3_to_geo(h3_exp)
는 geo_to_h3
와 반대로 H3 -> 좌표계로 변환시켜주는 메소드입니다. 주의할점은 기존 좌표를 그대로 반환하는게 아닌, 해당 H3의 중심좌표를 반환한다는 점입니다.
c.f) 6 level과 7 level의 차이는 어느정도일까?
H3 | Average Hexagon Area (km2) | Average Hexagon Edge Length (km) | Number of unique indexes | Distance |
---|---|---|---|---|
0 | 4,250,546.8477000 | 1,107.712591000 | 122 | 1827.9519km |
1 | 607,220.9782429 | 418.676005500 | 842 | 719.043km |
2 | 86,745.8540347 | 158.244655800 | 5,882 | 242.902km |
3 | 12,392.2648621 | 59.810857940 | 41,162 | 105.158km |
4 | 1,770.3235517 | 22.606379400 | 288,122 | 39.258km |
5 | 252.9033645 | 8.544408276 | 2,016,842 | 13.134km |
6 | 36.1290521 | 3.229482772 | 14,117,882 | 5.699km |
7 | 5.1612932 | 1.220629759 | 98,825,162 | 2.042km |
8 | 0.7373276 | 0.461354684 | 691,776,122 | 700.1m |
9 | 0.1053325 | 0.174375668 | 4,842,432,842 | 314.2m |
10 | 0.0150475 | 0.065907807 | 33,897,029,882 | 116.3m |
11 | 0.0021496 | 0.024910561 | 237,279,209,162 | 38.3m |
12 | 0.0003071 | 0.009415526 | 1,660,954,464,122 | 16.3m |
13 | 0.0000439 | 0.003559893 | 11,626,681,248,842 | 6.4m |
14 | 0.0000063 | 0.001348575 | 81,386,768,741,882 | 2.4m |
15 | 0.0000009 | 0.000509713 | 569,707,381,193,162 | 0m |
III. 활용 예시
각 지역별 버스정류장의 배치, 갯수, 접근성 등을 확인하여 버스정류장을 감축 및 증설할 계획을 갖고 있다고 가정합니다.
필요한 데이터를 문서로 확인하는 것도 방법이겠지만, 시각화를 통해 훨씬 빠르게 확인할 수 있을 것입니다.(이 때 H3 9 level은 약 0.1km^2 넓이로 한 선분이 약 300m 인 크기를 갖습니다. 한 버스정류장이 해당 영역만큼의 접근성을 갖고 있다고 가정해봅시다.)
위와 같이 간단한 코드를 통해 서울 전체의 버스정류장 배치와 접근성을 확인할 수 있으며, 어떤 지역에 증설이 필요하고 감소가 필요한지 의사결정하는데 도움을 줄 수 있습니다.