서울시 도로소통정보 시각화(with folium)-(2)

2023. 11. 28. 16:14Python

서울시 도로별 차량통행속도

https://topis.seoul.go.kr/refRoom/openRefRoom_1.do

TOPIS에서 제공하는 도로별 일자별 통행속도

TOPIS에서는 현재 서울시의 도로별 실시간 소통현황을 Open API로 제공할 뿐만 아니라 과거 데이터들도 위와 같은 사진과 같이 제공해줌으로 필요한 날짜를 다운로드 받아 활용할 수 있다. 참고로 이 데이터는 TOPIS에서 제공하는 서비스링크와 매핑된다.

 

전처리

데이터 매핑(JOIN)

파이썬을 통해 데이터프레임으로 불러와보자

일자별 도로별  평균 통행속도 데이터

링크아이디라는 컬럼이 존재하고 이는 지난시간에 서울시에서 제공하는 서비스링크와 같다고 생각하면 된다. 따라서 서울시 서비스링크 표준링크 아이디를 join문을 통해 매핑한 후 위의 데이터를 서비스링크와 매핑하면 된다. 아래는 해당 코드이다. 

# 서울시 서비스링크 표준링크아이디 매핑 정보
slinkmap=pd.read_excel('.\[2023-11-13]NODELINKDATA\서울시 표준링크 매핑정보_2023년3월 기준.xlsx')
slinkmap=slinkmap.astype(str) # 타입 변환

# 전국표준링크
link_df=gpd.read_file(".\[2023-11-13]NODELINKDATA\MOCT_LINK.shp",encoding='euc-kr')
link_df['geometry'] = link_df['geometry'].to_crs('EPSG:4326') #좌표계 변환

# 서울시 도로별 통행속도 
seoulspd=pd.read_excel('2023년 10월 서울시 차량통행속도.xlsx')
seoulspd['링크아이디']=seoulspd['링크아이디'].apply(lambda x:str(x))

# 전국표준링크 데이터와 서울시 표준링크 매핑 데이터를 표준링크를 사용해 Join
slink_df=pd.merge(left=slinkmap,right=link_df,left_on='표준링크아이디',right_on='LINK_ID', how ='inner')
slink_df=slink_df[['서비스링크','표준링크아이디','F_NODE','T_NODE','LANES','ROAD_RANK','CONNECT','geometry']]

# 위에 결과 테이블과 서울시 도로별 통행속도 데이터 서비스링크를 이용해 Join
final_df=pd.merge(left=slink_df,right=seoulspd, left_on='서비스링크' , right_on='링크아이디')

 

데이터 매핑(JOIN) 결과

최종적으로 위의 결과 데이터프레임을 확인해보면 서비스링크 하나에 여러 표준링크아이디가 있으며 다음과 같이 여러날짜가 존재하는 것을 확인할 수 있다.

최종 결과 테이블(final_df)

이제 이 데이터프레임에서 하루를 선택(ex 20231001)해서 추출해 도로 링크를 시각화를 하게 되면 다음과 같이 서울시에서 도로 통행속도를 서비스하고 있는 도로들을 시각화 할 수 있다.

도로별 통행속도 값을 가지는 도로 시각화

 

도로별 통행속도에 대한 범주화 컬럼 생성(color 컬럼)

이제 카카오 맵에서 서비스하고 있는 도로별 통행속도를 범주화 시켜보자 

카카오맵의 도로 통행속도 범주화 기준

카카오 맵에서 확인하면 각 색으로 예쁘게 도로 통행속도를 범주화 해놓은 것을 확인할 수 있는데 그 기준은 각 도로유형과 연결로별로 통행속도의 기준이 있다는 것을 확인할 수 있다.

folium을 이용해서 표준도로링크 아이디별로 해당 통행속도를 카카오맵과 유사하게 그려볼 예정인데 우선 시간을 하나 정하고 해당 시간에 대해서 도로별 통행속도를 시각화 해보자.

final_df1=final_df[final_df['일자']==20231001].copy() # 일자 하루 선택
tcolumn='15시' # 15시 시각화

 

그리고 함수를 통해서 각 표준도로링크아이디별 통행속도에 대한 범주화를 진행해보자.

def colordecide(connect, rank, spd): # 도로별 통행속도를 이용해서 색 지정
	# 도로 통행 속도가 결측 값일 때 해당 도로는 회색
    if np.isnan(spd): 
        return 'grey'
    # 고속도로일 경우  
    if rank == '101':  # 고속도로
        thresholds = [80, 50, 20, 0]
    # 도시국도와 일반국도일 경우 연결로에 대해서도 새로운 조건 지정
    # 도시국도 일경우
    elif rank == '102':  # 도시국도
    	# connect가 연결로에 대한 정보를 담고 있는 컬럼
        thresholds = [60, 40, 20, 0] if connect == '0' else [40, 20, 10, 0]
    # 일반 국도일 경우
    else:
        thresholds = [40, 20, 10, 0] if connect == '0' else [25, 15, 5, 0]    
    # 조건에 따른 thresholds 생성 완료
    
    # 루프문을 통해 해당 조건에 따라 색을 지정
    colors = ['green', 'yellow', 'orange', 'red']
    for threshold, color in zip(thresholds, colors):
        if spd >= threshold:
            return color

#위에서 만든 함수를 이용해 새로운 컬럼인 color 컬럼 생성
final_df1['color']=final_df1.apply(lambda x:colordecide(x['CONNECT'],x['ROAD_RANK'],x[tcolumn]),axis=1)

 

도로별 통행속도에 대한 범주화 컬럼 생성 결과

이제 각 표준링크마다 새로운 컬럼인 color가 생겨 색이 지정된 것을 확인할 수 있다.

color 컬럼 생성 결과

 

자 위의 데이터프레임을 이용해 각 표준링크별 도로 통행속도에 따른 색을 시각화 해보자. 우선 color 컬럼을 그대로 사용해서 시각화 해도 되나 카카오 맵과 같은 색을 사용해 시각화를 진행하기 위해 컬러를 맵핑해보자.

final_df2=final_df1.copy() 
# 카카오맵 컬러 매핑
color_mapping={'green':'#39d729','yellow':'#ffe300','orange':'#ffb629','red':'#ff3829','grey':'grey'}
final_df2['color']=final_df2['color'].apply(lambda x : color_mapping[x])

 

시각화

자 이제 데이터는 준비가 완료되었으니 시각화만 남았다.

기존에 썻던 시각화 차트와 유사하며 color라는 folium.PolyLine 함수의 파라미터에 color 컬럼을 지정해주면 

def linechart_color(df): #색을 이용한 folium 맵 라인 차트
    m = folium.Map(location=[37.5665, 126.9780], zoom_start=12)

    for _, row in df.iterrows(): # 데이터 프레임 로우 하나씩 Polyline 생성
        if isinstance(row['geometry'], MultiLineString) and len(row['geometry'].geoms) > 1:
            for line_string in row['geometry'].geoms:
                coordinates |= [(lat, lon) for lon, lat in line_string.coords]
                folium.PolyLine(locations=coordinates, color=row['color']).add_to(m) # color 파라미터에 새로 생성한 color 컬럼 지정
        else:
            coordinates = [(lat, lon) for lon, lat in zip(*row['geometry'].xy)]
            folium.PolyLine(locations=coordinates, color=row['color']).add_to(m)
    return m
    
    linechart_color(final_df2) # 시각화

 

결과는 다음과 같다.

시각화 결과

도로별 통행속도 최종 시각화

 

위의 그림은 2023년 10월 1일 15시에 해당하는 서울시 도로별 통행속도 시각화 결과이다. 보면 주말이어서 그런지 한강 주변과 서울시 외곽 도로에서 초록색(원활)이 많이 보이고 서울 중심부에서는 주황색(지체)과 빨강색(정체)도 조금씩 보인다.

 

위의 코드를 사용해서 서울시에서 제공하는 실시간 도로소통정보를 이용해 실시간으로 스트림릿을 활용해 시각화 해볼 수 도 있을 것으로 예상된다. 다만 카카오맵이나 TOPIS에서 서비스하고 있는 시각화처럼 확대정도에 따라서 주요도로와 세부도로 표출이 folium으로는 힘드며 일부 데이터가 매핑이 되지 않는 점에 대해서는 고민이 필요해 보인다.

 

※추후 도로의 하행 상행에 따라 화살표도 추가해볼 예정이다.