[SmoothRide] folium을 이용한 지도 시각화

SmoothRide

목록 보기
2/3

일단 나는 웹페이지를 만드는 것이기 떄문에, 시각화를 먼저 가능한지 확인하는 것이 중요하다고 생각했다. 일단 가장 간단하게 돌아가는 것을 확인하기 위해, 파이썬의 folium 라이브러리를 이용하여 지도 시각화를 사용하였다.
당연히 실제로는 다른 걸로 할꺼지만, 돌아가는지 내 눈으로 직접 확인하고 싶어서 이 라이브러리를 사용하였다.

우선 지도 시각화를 하려면 표준링크라는 것을 알아야 한다.

https://www.its.go.kr/nodelink/

노드링크는 교통정보의 원활한 사용을 위해 단일화된 ID 체계를 사용하는 도로체계이다.
전국에 있는 노드들에 번호를 매기고, 이 노드와 노드 사이를 연결하는 링크를 표현해서 전국의 지도를 표현하는 체계라고 생각하면 편하다.

처음 데이터 할때는 이걸 서비스링크로 바꾸고.. 어쩌고.. 했는데 데이터를 맞추니 훨씬 편하다. 역시 데이터를 잘 찾아보는 것도 영향이 엄청난 것 같다. 굳이 돌아갈 필요는 없으니깐.

지도를 제대로 한 적은 처음이라 고생을 좀 하는 중이다.
우선 서울의 노드정보를 얻기 위해서는 shp 파일을 다운받아야 한다.

지우기 귀찮다. 위아래..
아무튼 저기에서 노드링크들을 다운받을 수 있다. 다만 조심해야 하는 것은, 현재 12-27꺼는 일부 도로만 들어있는 긴급 배치용도라 의미가 없다. 전체 노드 링크를 받고 싶으면 11-29일꺼를 사용하면 된다.

파일을 다운받으면 다음과 같이 생겼다.
각각 파일의 뜻하는 바가 있는데, 여기서 shp 파일이 메인이다. MOCT_LINK와 MOCT_NODE가 보인다.

이걸 그럼 어디서 여냐? 라고 하면 QGIS라는 프로그램이 있다.
https://qgis.org/download/
여기서 다운받으면 된다. 어쨌든 다운받으면 빈 프로젝트가 있는데, 여기서

레이어 - 레이어 추가 - 벡터 레이어 누르고 저 두 파일을 넣어주면 된다. 그럼 저렇게 뜬다. 화면은 링크만 보이게 해둔 거고, 실제로는 점들이 같이 뜬다.
그리고 속성 테이블을 누르면 다양한 정보들이 뜬다. 내가 근데 여기서 원하는 거는 저 지도의 위도와 경도를 알아야 한다. 왜냐면 그래야 지도를 띄웠을 때 저 정보들을 표시할 수 있기 때문이다.


먼소린지 이해가 힘드니, 처음부터 설명하겠다. folium을 통해 서울 지도를 만들면 기본은 다음과 같다.

우리가 해야 하는 것은 실시간 교통량 데이터를 통해 속도에 따라 다른 색으로 표현해야 하기 때문에, 저 지도 위에다가 노드와 링크를 겹쳐야 한다.
folium 지도는 위도와 경도로 되어있기 때문에, qgis에서도 좌표계를 설정해야된다 이얘기다. qgis 화면에서 오른쪽 아래를 보면 원래 좌표계 설정 안되어있음 버튼이 있다. 이걸 누르면 좌표계를 설정할 수 있다.

필터에서 wgs84 좌표계를 누르면 된다. 이게 위도 경도 좌표계다. 좌표계에 대한 공부도 하려고 한다. 공부 안하면 의미가 없으니깐.
암튼 위치를 바꾼 다음에 Ctrl Alt T를 같이 누르면 툴박스가 뜨는데, (옆에 있다) 거기서 x/y 필드를 레이어에 추가 누르면 추가할 수 있다.
좌표계 wgs84로 설정하고, 실행을 누르면 레이어 쪽에 하나가 생긴다. 거기에 오른쪽 클릭 - 내보내기 - 피처를 다른 이름으로 내보내기 누르면 된다. csv로 내보내자.
이런 식으로 모든 필드를 다 보낼 필요는 없다. 데이터가 너무 커져서 렉이 많이 걸린다.


노드 파일 csv의 일부분이다. 저 x와 y를 통해 folium에서 시각화가 가능하다.
링크는 다음과 같다.
✔️ LINK_ID: 도로 링크 고유 ID
✔️ F_NODE, T_NODE: 출발 및 도착 노드 ID
✔️ ROAD_NAME: 도로명
✔️ MAX_SPD: 제한 속도
✔️ LENGTH: 도로 길이이제 데이터들은 준비되었으니, 지도에서 표현해보자.

import pandas as pd
import folium

# 1️⃣ 노드 및 링크 데이터 로드 (파일 경로 직접 지정)
node_file_path = "coord/coord_utf.csv"
link_file_path = "coord/link_utf.csv"

node_df = pd.read_csv(node_file_path, encoding="utf-8", low_memory=False)
link_df = pd.read_csv(link_file_path, encoding="utf-8", low_memory=False)


# 2️⃣ 서울 지역 노드만 필터링
seoul_nodes = node_df[
    (node_df["x"] >= 126.7) & (node_df["x"] <= 127.3) &
    (node_df["y"] >= 37.3) & (node_df["y"] <= 37.7)
]

# 4️⃣ 서울 노드 리스트 생성
seoul_node_ids = set(seoul_nodes["NODE_ID"])

# 5️⃣ 서울 지역에 속하는 링크만 필터링 (출발 & 도착 노드가 둘 다 서울에 있는 경우)
seoul_links = link_df[
    (link_df["F_NODE"].isin(seoul_node_ids)) & 
    (link_df["T_NODE"].isin(seoul_node_ids))
]

# 6️⃣ 노드 데이터를 딕셔너리로 변환 (빠른 조회를 위해)
node_dict = seoul_nodes.set_index("NODE_ID")[["y", "x"]].to_dict(orient="index")

# 7️⃣ 서울 중심 좌표 설정
seoul_center = [37.5665, 126.9780]

# 8️⃣ Folium 지도 생성
m = folium.Map(location=seoul_center, zoom_start=12)

# 9️⃣ 서울 노드 데이터 지도에 추가 (파란색 점)
for node_id, coords in node_dict.items():
    folium.CircleMarker(
        location=[coords["y"], coords["x"]],
        radius=2,
        color="blue",
        fill=True,
        fill_color="blue",
        fill_opacity=0.6,
        tooltip=f"NODE_ID: {node_id}"
    ).add_to(m)

# 🔟 서울 도로 링크 지도에 추가 (빨간색 선)
for _, row in seoul_links.iterrows():
    f_node = row["F_NODE"]
    t_node = row["T_NODE"]

    # 시작 노드와 종료 노드 좌표 찾기
    if f_node in node_dict and t_node in node_dict:
        f_coords = node_dict[f_node]
        t_coords = node_dict[t_node]

        folium.PolyLine(
            locations=[(f_coords["y"], f_coords["x"]), (t_coords["y"], t_coords["x"])],
            color="red",
            weight=2,
            opacity=0.8,
            tooltip=f"도로명: {row['ROAD_NAME']}<br>제한 속도: {row['MAX_SPD']} km/h<br>길이: {row['LENGTH']} m"
        ).add_to(m)

# 🔟 지도 파일 저장
map_file = "seoul_link_map.html"
m.save(map_file)

print(f"서울 지역 지도 파일이 저장되었습니다: {map_file}")

서울시만 한 이유는, 전국을 하면 html 파일이 너무 커진다. 서울도 애초에 확대하면 너무 오래걸린다... 사실 이 코드가 중요한건 아니니깐 패스.
그래서 어찌저찌 돌려보면


요렇게 잘 보여준다. 툴팁으로 노드나 링크에 대한 정보도 보여주도록 하였기 때문에, 아주 편하다.
이거는 이미 있는 데이터들을 바탕으로 기록된 전체 링크들을 표현한 것이고, 다음에는 여기서 실시간 데이터로 받아오는 링크들이 어디있는지 비교해보도록 하겠다.

0개의 댓글