-
21년 1월 서울 공공자전거 대여 이력 데이터 분석 & 시각화 with Python, Pydeck, Plotly, Sankey DiagramData Analysis/LifeStyles 2021. 6. 8. 16:35
이번 포스팅에서는 아래 "서울시 공공자전거 대여 이력 정보" 데이터를 가지고 생키 다이어그램과 이동 경로를 지도에 시각화하는 방법을 소개하고자 한다. 데이터 분석보다는 파이썬을 통한 데이터 시각화하는 코드를 다루는 내용으로 보시면 될 것 같다.
Data Source:
http://data.seoul.go.kr/dataList/OA-15182/F/1/datasetView.do
데이터는 21년 1월 자료를 사용하도록 하겠다. 파일을 다운로드하면 공공 자전저 대여 위치, 반납 위치, 대여 시간 등 여러 정보를 확인할 수 있을 것이다
파이썬으로 Sankey Diagram:
이번 포스팅에는 합정을 중심으로 분석해보고자 한다. 합정 부근에서 공공자전거를 대여한 이용객들이 과연 어디에 자전거를 다시 반납했는지를 한번 생키 차트로 알아보겠다.
import pandas as pd import plotly.graph_objects as go import plotly.express as pex import numpy as np df=pd.read_csv('D:/Download/공공자전거.csv',encoding='cp949') df2=df[df['대여 대여소명'].str.contains('합정')] table=pd.DataFrame(df2.groupby(['대여 대여소명','반납대여소명']).count()['자전거번호']).reset_index() table=table.sort_values(by='자전거번호',ascending=False) table.columns=['대여 위치','반납 위치','Counts'] table2=table[table['Counts']>20] table2['대여 위치']=table2['대여 위치'].apply(lambda x:x+'(대여 장소)') table2['반납 위치']=table2['반납 위치'].apply(lambda x:x+'(반납 장소)') all_nodes = table2['대여 위치'].values.tolist() + table2['반납 위치'].values.tolist() source_indices = [all_nodes.index(a) for a in table2['대여 위치']] target_indices = [all_nodes.index(b) for b in table2['반납 위치']] colors = pex.colors.qualitative.D3 node_colors_mappings = dict([(node,np.random.choice(colors)) for node in all_nodes]) node_colors = [node_colors_mappings[node] for node in all_nodes] edge_colors = [node_colors_mappings[node] for node in table2['대여 위치']] fig = go.Figure(data=[go.Sankey( node = dict( pad = 20, thickness = 20, line = dict(color = "black", width = 1.0), label = all_nodes, color = node_colors, ), link = dict( source = source_indices, target = target_indices, value = table2['Counts'], color = edge_colors, ))]) fig.show() fig.write_html('sankey.html')
아래 차트와 같이 합정 부근에는 총 5개의 공공자전거 대여 장소(합정역 7번 출구, 합정동 주민센터, 구 합정동 주민센터, 합정역 1번 출구, 합정역 5번 출구)가 있다. 해당 5개 대여 장소에서 자전거를 대여한 이용객들이 과연 어디에 반납했는지 아래 생키 차트에서 볼 수 있을 것이다. 마우스를 위에 호버링 하면 대여-반납 경로별 대여 횟수를 확인할 수 있을 것이다. 라인 굵기가 두꺼워질수록 해당 경로의 횟수가 많다는 뜻으로 해석하면 된다.
대부분 대여한 장소에서 반납하는 점을 볼 수 있다. 합정역 7번출구 앞에서 대여한 이용객이 다시 해당 장소에 반납한 경우 100번으로 가장 많이 나타나고 있다.
Pydeck으로 지도 시각화:
다음으로 자전거 대여가 가장 활발히 이루어지고 있는 합정동주민센터를 중심으로 여기서 대여한 사람들이 어디에 자전거를 다시 반납했는지 지도에 시각화해보도록 하겠다.
해당 분석에는 UBER에서 만든 Pydeck 라이브러리를 사용해보도록 하겠다.(pip install pydeck 하면 사용 가능)
데이터 추출 코드 관련 참고 사항:
- 반납 장소가 동일하게 합정동주민센터의 경우 제외
- 카카오 API를 통해 반납 장소 위도, 경도 추출(다만 주소가 명확하지 않아 100% 정확하지는 않음)
- 카카오 API에서도 위도, 경도가 나오지 않을 경우가 있어서 일부 반납 주소는 수작업
table_=table[table['대여 위치']=='합정동주민센터 앞'] table_2=table_[table_['Counts'] > 10] table_3=table_2[1:] table_3['반납 위치']=table_3['반납 위치'].apply(lambda x:x.strip(' 앞').strip(' 옆').strip(' 건너편')) import requests lat=[] lon=[] for i in table_3['반납 위치']: try: url = f'''https://dapi.kakao.com/v2/local/search/keyword.json?query={i}&y=37.551702&x=126.911720&radius=10000''' print(i) headers = { "Authorization": "KakaoAK ~~~" } #json 형태로 데이터가 주어진다 places = requests.get(url, headers = headers).json()['documents'] lat.append(places[0]['y']) lon.append(places[0]['x']) except: lat.append('') lon.append('') table_3['lat']=lat table_3['lon']=lon table_3.loc[table_3['반납 위치']=='(구)합정동 주민센터',['lat']]=37.549527 table_3.loc[table_3['반납 위치']=='(구)합정동 주민센터',['lon']]=126.905731 table_3.loc[table_3['반납 위치']=='신한은행 서교동금융센터점',['lat']]=37.557432 table_3.loc[table_3['반납 위치']=='신한은행 서교동금융센터점',['lon']]=126.918426 url = f'''https://dapi.kakao.com/v2/local/search/keyword.json?query=합정동 주민센터&y=37.551702&x=126.911720&radius=10000''' headers = { "Authorization": "KakaoAK ~~" } #json 형태로 데이터가 주어진다 places = requests.get(url, headers = headers).json()['documents'] table_3['slat']=places[0]['y'] table_3['slon']=places[0]['x'] table_3['slat']=table_3['slat'].astype(float) table_3['slon']=table_3['slon'].astype(float) import pydeck as pdk layer = pdk.Layer( 'LineLayer', table_3, get_source_position='[slon, slat]', get_target_position='[lon, lat]', get_width='Counts/5', get_color=f'[Counts*100,0,0]', pickable=True, auto_highlight=True ) view_state = pdk.data_utils.compute_view(table_3[['slon', 'slat']].values) view_state.zoom = 13 r = pdk.Deck(layers=[layer], initial_view_state=view_state) r.show() r.to_html('경로.html')
위 코드가 문제 없이 돌아간다면 아래와 같은 결과물을 확인할 수 있을 것이다. 대여장소 - 반납 장소 기준으로 라인을 그려봤는데, 마우스를 위에 호버링 하면 관련 위치 정보를 확인할 수 있을 뿐만 아니라 얼마나 많이 이 경고 기준으로 대여와 반납이 일어났는지도 확인할 수 있다. 해당 횟수가 많을수록 라인이 두꺼워진다는 점 참고 바란다.
'Data Analysis > LifeStyles' 카테고리의 다른 글
네이버 쇼핑인사이트 - 종근당 락토핏 유산균 검색 클릭량 추이 가져오기 With Python (0) 2021.06.25 2013년 ~ 2020년 연도별 한강공원 방문 이용객 수 데이터 분석 With Python, folium, Plotly (0) 2021.06.13 제주도 렌터카 업체 정보 분석 & 시각화 With Python & Mapbox (0) 2021.06.07 서울 크로스핏 박스 지도 시각화 with Python, Mapbox, 카카오 API (0) 2021.05.31 NBA Data Analysis - Top 10 포인트 가드의 어시스트/턴오버 분석 (0) 2021.05.19