이것저것 기록

[python, GIS] OSMnx로 POI 데이터 추출 및 활용 본문

코린이/실무를 위한 코딩 기록

[python, GIS] OSMnx로 POI 데이터 추출 및 활용

anweh 2020. 12. 16. 19:25

이전 포스팅과 이어지는 내용!

이전 포스팅에서는 특정 좌표를 지오코딩 한 후에

인근의 POI 데이터를 받아서, 어떤 종류의 POI가 얼마나 있는지 확인하는 task를 진행했다. 

이번에는 POI 데이터를 추출하고 활용하는 방법을 다뤄보려고 한다. 

 

 

1. 필요한 라이브러리 불러오기 

import networkx as nx 
from geopy.geocoders import Nominatim
import osmnx as ox 
import shapely 
import pandas as pd
from shapely import geometry
from descartes.patch import PolygonPatch
from shapely.geometry import LineString

 

 

2. 지난 코드 

geolocoder = Nominatim(user_agent = 'South Korea')

def geocoding(address): 
    geo = geolocoder.geocode(address)
    crd = (geo.latitude, geo.longitude)
    print(crd)
    return crd


# osmnx.pois.pois_from_address로 해당 좌표 인근의 POI 정보 불러오기 
tags = {'amenity': True}

address_list = ['서울대입구역',
'도림로 264',
'현충로 213']


crds = []
demo = dict()
crd = geocoding(address_list[0])
crds.append(crd)
pois = ox.pois.pois_from_point(crd, tags=tags, dist=500)

특정 주소를 지오코딩해서, 지오코딩한 좌표 인근의 poi 데이터를 불러와 pois에 저장하는 것까지가 지난 포스트였다. 

실행 결과는 다음과 같다. 

 

 

3. name 컬럼의 결측값 처리 

pois = pois.dropna(axis=0, subset=['name'])
pois.reset_index(inplace=True)

name에 결측값 (nan)이 있는 자료는 그냥 없애줬다. 

왜냐하면 이름이 뭔지 모르는 POI는 그 노드가 어디를 나타내는 것인지에 대한 정보가 없기 때문이다. 

dropna()를 사용해서 결측값을 제거해주었고, 

제거해준 곳은 인덱스가 비기 때문에 reset_index()를 사용하여 결측값 삭제로 인해 빈 인덱스를 메꾸어줬다. 

 

 

4. POI의 좌표 정보 추출 

pois_df = pd.DataFrame(index=range(0, len(pois)), columns=['poi_osmid', 'poi_x', 'poi_y'])
amenity_coord = dict()
for i in range(len(pois)):
    shapely_obj = pois.loc[i, ['geometry']]
    
    if shapely_obj[0].type == 'Point':
        x_crd = shapely_obj[0].xy[0][0]
        y_crd = shapely_obj[0].xy[1][0]
        xy_crd = (x_crd, y_crd)
        amenity_coord[pois.loc[i, ['name']][0]] = [pois.loc[i, ['amenity']][0], xy_crd]
        pois_df.loc[i] = [pois.loc[i, ['osmid']][0], x_crd, y_crd]
    
    if shapely_obj[0].type == 'Polygon': 
        x_crd = shapely_obj[0].centroid.xy[0][0]
        y_crd = shapely_obj[0].centroid.xy[1][0]
        xy_crd = (x_crd, y_crd)
        amenity_coord[pois.loc[i, ['name']][0]] =  [pois.loc[i, ['amenity']][0], xy_crd]
        pois_df.loc[i] = [pois.loc[i, ['osmid']][0], x_crd, y_crd]

위에서 생성한 poi 데이터프레임엔 'geometry' 컬럼이 있다. 

POINT 아니면 POLYGON의 형태인데, 각각에 대해서 조금 다른 처리를 해줬다. 

일단 shapely_obj에 'geometry' 정보를 불러왔다. 

POINT 타입이라면 곧바로 (x, y)좌표를 뽑아서 저장했고,

POLYGON 타입이라면 중심점의 (x, y)좌표를 뽑아 저장했다. 

총 두 가지의 아웃풋이 나온다. 

첫 번째는 amenity_coord, 두 번째는 pois_df이다. 

amenity_coord

amenity_coord는 key로 POI의 이름을 갖고, value로 amenity_type과 좌표를 갖는다. 

앞선 포스팅에서 얘기했다시피 amenity_type은 다양하게 많는데 나는 모든 type을 고려하기로 했다. 

pois_df

pois_df는 pois_osmid, poi_x, poi_y 이렇게 총 세개의 컬럼을 갖는다. 

pois_osmid는 각각의 POI가 OSM상에서 가지고 있는 고유 id이고, 이 id를 사용해서 불러온 (x, y) 값이 각각 poi_x / poi_y에 저장되어 있는 형태다.  

 

 

 

다음 포스팅에서는 추출한 POI 노드를

기존의 도로네트워크 그래프에 추가하여 새로운 그래프를 생성하는 방법에 대해서 포스팅 하려고 한다. 

Comments