이것저것 기록

[python, GIS] 서울시 지하철역 노선정보+좌표 데이터 구축하기 본문

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

[python, GIS] 서울시 지하철역 노선정보+좌표 데이터 구축하기

anweh 2021. 4. 17. 16:44

서울시 지하철역 좌표와, 그 지하철역을 지나는 호선 정보를 포함한 데이터가 없어서 만들었습니다. 

두 가지 데이터를 사용하여 구축하였습니다. 

 

데이터와 코드는 깃헙에 올려놨으니 참고해주세요! 

 

github.com/henewsuh/subway_crd_line_info

 

henewsuh/subway_crd_line_info

지하철역 좌표와 노선 정보를 통합하는 코드. Contribute to henewsuh/subway_crd_line_info development by creating an account on GitHub.

github.com


1. 라이브러리 및 데이터 불러오기 

import pandas as pd
import os 
from geopandas import GeoDataFrame
import pickle
from shapely.geometry import Point

cur_path = os.getcwd() # 경로 설정

subway_crd = pd.read_csv('지하철역_좌표.csv', encoding='cp949')
subway_line= pd.read_csv('서울교통공사 노선별 지하철역 정보.csv', encoding='cp949')

좌표 정보는 subway_crd로, 노선 별 정보는 subway_line으로 불러왔다. 

subway_crd는 역이름과 좌표만 있는 반면, subway_line에는 역이름과 해당 역을 지나는 노선 정보가 들어있기 때문에 이 두 데이터를 합칠 것이다. 

 

 

 

2. 지하철역 좌표에 노선 정보 추가하기  

line_ls = []
for i in range(len(subway_crd)): 
    cur_subway = subway_crd.iloc[i]['역이름']
    matched_line = subway_line.loc[subway_line['전철역명'] == cur_subway]
    
    if len(matched_line) > 0 : 
        line_ls.append(list(matched_line['호선']))
        
    else: 
        line_ls.append(None)

subway_crd['호선'] = line_ls # 호선 정보 부여
subway_crd.dropna(subset=['호선'], inplace=True, axis=0) # 수도권 지하철역 좌표는 노선 정보가 안들어갔으므로 제거 

subway_crd['geometry'] = subway_crd.apply(lambda x: Point(x['x'], x['y']), axis=1) # 좌표 정보를 합쳐서 geometry 정보 부여  
subway_crd_gdf = GeoDataFrame(subway_crd, crs='EPSG:4326', geometry='geometry') # 좌표계 지정

subway_crd를 돌면서 해당 역이름과 일치하는 역이름 정보를 subway_line에서 찾은 후, 그 역을 지나는 노선 정보를 line_ls에 차곡차곡 쌓아주었다. 

그리고 따로 놀던 x, y 좌표를 하나의 좌표로 합친 다음에 geometry 속성으로 설정하여 GeoDataFrame을 구축했다.

subway_crd_gdf를 확인해보면 다음과 같다. 

 

subwa_crd_gdf

'호선' 컬럼에 각 역에 정차하는 호선 정보를 list 형태로 추가하였다. 나중에 length를 확인했을 때 몇 개의 노선이 지나는지 확인할 수 있다. 

그리고 'geometry' 컬럼에는 (x, y)좌표를 합쳐서 기하 정보로 추가해주었다.

이렇게 하면 거리 계산과 지도 시각화가 가능해진다. 

하지만 호선 정보를 list로 쌓았기 때문에, .shp이나 .geojson으로 export가 불가능했다. 

그래서 bin 파일로 이 정보를 저장하려고 한다. 

 

 

 

3. 저장 + 불러오기 함수 설정 

def write_data(data, name):
    with open(name + '.bin', 'wb') as f:
        pickle.dump(data, f)
        
        
def load_data(name):
    with open(name + '.bin', 'rb') as f:
        data = pickle.load(f)
    return data  

bin파일로 데이터를 저장하면 데이터프레임이나 딕셔너리, 리스트 등 다양한 형태의 자료를 있는 그대로 저장하고, 있는 그대로 개발 환경으로 불러와 사용할 수 있어서 무척 편리하다. 

 

 

 

4. 데이터 저장 

# bin 데이터 -- 파이썬 활용 용도 (ArcGIS/QGIS 시각화 용도 x)
write_data(subway_crd_gdf, 'subway_crd_4326')
subway_crd_5179 = subway_crd_gdf.to_crs(epsg=5179) # 거리 계산을 위한 좌표계로 변환 후 저장
write_data(subway_crd_5179, 'subway_crd_5179')


# 나중에 bin 데이터 다시 불러올 때 
subway_crd_4326 = load_data('subway_crd_4326')
subway_crd_5179 = load_data('subway_crd_5179')


# 노선 정보를 빼고 좌표 데이터 
subway_crd_5179 = subway_crd_5179.drop(['호선'], axis=1)
subway_crd_5179.to_file('subway_crd_5179.geojson', driver='GeoJSON')

두 가지 형태로 데이터를 저장했다. 

우선 bin 데이터는 파이썬 활용 용도이다. 좌표계는 경위도 좌표계인 4326과 거리 계산을 위한 5179, 두 개로 저장했다. 

그리고 노선 정보를 빼고, 이 데이터의 좌표를 시각화해보기 위해 geojson형태로도 저장해봤다. 

 

geojson파일을 QGIS에서 시각화한 모습

자, 보다시피 위치 좌표가 정확한 것을 확인할 수 있다. 

이렇게 해서 지하철 좌표와 노선 정보 통합 데이터 구축 끝!! 

 

 

 

 


+ 하소연... 

 

최근 도로명주소 기본도의 지하철 출입구 데이터를 열어보고 깜짝 놀랐다. 

속성 데이터가 정말 뒤죽박죽 엉망인 것. 

지하철 출입구 번호만 있고, 그 지하철역에 몇호선이 지나는지 이러한 기본적인 정보도 추가를 안 해놨다. 

 

여기저기 뒤져봐도, 지하철 출입구 + 그 지하철역을 지나는 노선 데이터를 찾을 수 없었다. 

참나... 이런 수준의 데이터를 백날 공공으로 오픈해봤자, 무슨 소용이 있을까? 

정말 양질의 데이터를 제대로 제공해줬으면 좋겠다ㅜㅠ

 

Comments