프로젝트 - 따릉이 데이터 지도 시각화

minjoo·2022년 8월 1일
0

플레이데이터

목록 보기
4/6

주제 선정

첫 프로젝트가 시작되었다. 그동안 Python을 기반으로 데이터를 시각화하는 다양한 방법을 배웠고, 이번 프로젝트의 목적은 그동안 배운 방법을 활용해보는 것이었다.

프로젝트 소재로 '따릉이'를 선정한 것은 이런 목적을 고려해서였다. 수업 중에 지도 활용 패키지인 Holium을 배웠으니 지도를 활용한 시각화를 해보고 싶었다. 지도 시각화를 할 만한 데이터 중 구하기 쉬웠던 게 공공데이터인 따릉이 이용내역이었다.

데이터 수집 및 전처리

https://data.seoul.go.kr/dataList/OA-15182/F/1/datasetView.do

우리 조는 서울 열린데이터광장에서 따릉이 이용내역 관련 데이터를 내려받아 사용했다. 서울 열린데이터광장에는 링크한 데이터 이외에도 대여소별 위도와 경도 등 다양한 종류의 데이터가 있어서 목적에 따라 활용하기 좋다.

데이터를 수집하는 것은 별로 어렵지 않았지만, 방대한 양의 데이터를 전처리하고 가공하는 것은 어려웠다. 우리가 이용한 '서울특별시 공공자전거 대여이력 정보' 데이터는 서울특별시 전역의 모든 따릉이 대여소에서 기록된 따릉이 이용 내역을 월별로 정리한 것이다. CSV 파일 한 개에 100~200만 건 이상 되는 이용 내역이 정리되어 있기도 했는데, 파일의 크기가 너무 크다 보니 엑셀로 원본 데이터를 열었을 때 확인 불가능한 부분이 생기거나 데이터 처리 중 Colab이 작동을 멈추는 등 다양한 문제가 생겼다.

우리 조는 우리가 통제할 수 있는 수준으로 데이터를 줄이기 위해 목표를 선명하게 설정했다. 서울 시내에서 딱 두 개, '강남구청'과 '강서구청' 대여소에서 대여된 자전거만을 대상으로 삼아 이 자전거들이 어디로 이동하는지, 어느 시간대에 주로 이동하는지를 시각화하기로 했다.

전처리 과정에서는 대여소 이름에 따른 에러가 발생했다. 대여소가 없어지거나 이름이 바뀐 경우도 있었지만, '주공아파트 11단지'와 '주공아파트11단지'가 다른 이름으로 인식되는 등 띄어쓰기나 표기법만 다를 뿐 가리키는 대상이 같은 단어가 다른 장소로 인식되는 경우가 더 많았다. 다행히 데이터에서는 각 대여소별 고유 번호를 지정해 두었고, 우리는 고유 번호를 기준으로 대여소를 분류했다.

데이터 시각화

데이터 전처리 과정을 거쳐 아래와 같은 형식의 데이터프레임을 만들었다. 아래는 강서구청에서 출발한 자전거를 반납 대여소명으로 나열한 것이고, 강남구청 출발 자전거를 기준으로도 같은 형식의 데이터프레임을 만들었다.

지도 시각화

지도에는 원래 Holium 패키지를 이용하여 반납 대여소를 Marker로 찍으려고 했는데, 데이터가 너무 많다보니 Marker가 너무 많이 찍혀서 보기 좋지 않고, 이 과정에서 Colab이 멈추는 등 문제가 발생하였다. 그래서 클러스터 단위로 마커를 찍었다.

from folium.plugins import MarkerCluster

map = folium.Map(location =[lat,lng], zoom_start=12 ) #강남구청과 강서구청의 중간지점을 기준으로해서 지도를 보여줄 예정입니다.


# 마커 찍기

mc = MarkerCluster() # 반납장소 클러스터 마크 찍기
for i in final.index:
    mc.add_child(    
        folium.Marker(location = [final.loc[i, '반납위도'], final.loc[i, '반납경도']]
              ,icon = folium.Icon(color='blue', icon='flag')
    ))
#근처 반납장소들의 좌표들을 찍어서 지도에 표시해 보겠습니다.    
map.add_child(mc)


folium.Marker([ region.loc[0, '위도'], region.loc[0, '경도']],
        popup='강남구청',icon = folium.Icon(color='red', icon='star')).add_to(map)

folium.Marker([ region.loc[1, '위도'], region.loc[1, '경도']],
          popup='강서구청',
        icon = folium.Icon(color='red', icon='star')).add_to(map)

#이번에는 강남구청, 강서구청 마크추가
    
map

대여 장소와 반납 장소를 선으로 이어보기도 했다.

# 강남구청 polyline 찍기

m = folium.Map([37.541, 126.986], zoom_start=12)
mc = MarkerCluster()   #강남구청의 위도, 경도를 기준으로 해서 보여줌.

folium.Marker([region.loc[0, '위도'], region.loc[0, '경도']],
        popup='강남구청',
        icon = folium.Icon(color='red', icon='star')).add_to(m) #강남구청의 위치좌표 찍기

for i in df_gangnam.index:
    mc.add_child(    
        folium.Marker(location = [df_gangnam.loc[i, '반납위도'], df_gangnam.loc[i, '반납경도']]
              ,icon = folium.Icon(color='blue', icon='flag')
    ))
    
    folium.PolyLine([[region.loc[0, '위도'], region.loc[0, '경도']], 
                     [df_gangnam.loc[i, '반납위도'], df_gangnam.loc[i, '반납경도']]]).add_to(m) #강남구청 대여소에서 이용한 자전거를 근처 반납장소까지 얼마나 이용했는지 라인으로 연결해 봤습니다.
    
m.add_child(mc)
m

위 사진은 강남구청에서 출발한 자전거를 Cluster + Polyline 그려놓은 결과물이다.

강남구청, 강서구청에서 출발한 자전거가 가장 많이 이용한 반납 장소 10군데를 뽑고, 각 장소의 이름을 표시해 보았다.

number_south = df_gangnam['반납장소'].value_counts()

for i in range(0, 11):
    print(number_south.index[i]) #강남구청에서 자전거를 가장 빌려서 반납한 사람들이 가장 많이 이용하는 반납 대여소 10군데를 뽑아봤습니다.
    
df_gangnam_top10 =[]

number_south = df_gangnam['반납장소'].value_counts()

for i in range(0, 11):
    df_gangnam_top10.append(number_south.index[i]) #이 대여소들을 리스트화해서 추가했습니다.
    
df_gangnam_top10 =final[final['반납장소'].isin(df_gangnam_top10)] #이 반납장소를 이용한 고객들만 다시 한번 체크해서 전체 데이터를 뽑아봤습니다.

df_gangnam_top10_unique= df_gangnam_top10.drop_duplicates('반납장소') #여러개의 반납장소들이 겹치기 때분에 하나만 출력함.

m = folium.Map([37.518070, 127.047119], zoom_start=16) #강남구청의 좌표를 기준으로 해서 화면을 띄우겠습니다.
mc = MarkerCluster() #위 지도는 MarkerCluster로 표시합니다.


folium.Marker([ region.loc[0, '위도'], region.loc[0, '경도']],
        popup='강남구청',
        icon = folium.Icon(color='red', icon='star')).add_to(m) #강남구청의 좌표를 우선 찍었습니다.

for i in df_gangnam_top10_unique.index:
    folium.Marker([df_gangnam_top10_unique.loc[i, '반납위도'], df_gangnam_top10_unique.loc[i, '반납경도']],
                  popup = df_gangnam_top10_unique.loc[i,'반납장소'],
                  icon =folium.Icon(color="green")).add_to(m)  #반납장소의 이름표시함.

for i in df_gangnam_top10 .index:
    mc.add_child(    
        folium.Marker(location = [df_gangnam_top10 .loc[i, '반납위도'],df_gangnam_top10 .loc[i, '반납경도']]
              ,icon = folium.Icon(color='blue', icon='flag') #강남구청에서 자전거를 빌려서 근처에 이용한 반납함들을 체크했습니다.
    ))
    
    folium.PolyLine([[region.loc[0, '위도'], region.loc[0, '경도']], 
                     [df_gangnam_top10 .loc[i, '반납위도'], df_gangnam_top10.loc[i, '반납경도']]]).add_to(m) #강남구청과 근처 반납함들을 체크해서 폴리라인으로 나타내봤습니다.
    
m.add_child(mc)
m 

강남구청과 강서구청 모두 대여 장소와 가까운 지역에서 따릉이가 주로 이용되는 경향을 보였다.

시간대별 시각화

데이터프레임에서 날짜와 시간을 분리한 뒤, 요일별, 일별, 월별 등으로 이용자수를 분리하여 데이터프레임을 만들고 시각화했다. 파이 차트, 막대그래프, 꺾은선그래프 등으로 시각화하는 데에는 Plotly를 사용하였다.

# 월별 따릉이 이용자 수 (강남 + 강서)
import plotly.graph_objects as go
import plotly.io as pio 
pio.templates.default = "plotly_dark"
fig = go.Figure(go.Scatter(
    x = total_month.index,
    y = total_month['총 수'],

))

fig.update_layout(
    xaxis = dict(
        title ='월별 따릉이 이용자 수',
        tickmode = 'linear',
        tick0 = 0,
        dtick = 0.75
    )
)

시각화 결과, 강서구청의 따릉이 이용객이 강남구청에 비해 압도적으로 많은 것으로 드러났다. 여기에는 여러 가지 이유가 있겠지만, 강서구청 근처가 마곡 등 유동인구가 많은 지역인 데 반해 강남구청 근처는 아파트단지 위주인 점, 강서에 비해 강남 지역은 전동킥보드 등 따릉이의 대체재가 활발히 운영 중인 점이 주된 이유로 꼽혔다.

예상대로 출퇴근 시간대, 여름철에 이용객 수가 많았다. 특이하게도 강서구청에 비해 강남구청에서 아침 출근시간에 비해 오후 4시 즈음에 높은 이용률을 보였는데, 근처 학교에 다니는 학생들이 통학용으로 따릉이를 이용하는 것으로 추정되었다.

좋았던 점, 아쉬웠던 점

첫 프로젝트를 경험하며 Pandas, Plotly, Holium 등 배웠던 것을 직접 사용해본 점이 좋았다. 큰 규모의 데이터를 활용하며 애로사항을 겪어 보고, 문제를 해결하기 위해 목표를 수정하는 과정을 거친 것이 유익했다. 200만 줄 이상 되는 대용량 데이터는 엑셀로 열리지 않는다는 게 상당히 놀라웠는데, 데이터 양 자체가 유익한 도전 과제가 될 수 있다는 게 더 놀라웠다.

기획자 출신인 조원 분의 사회 경력과 다른 조원들의 협력 덕분에 의사 결정이 빠르면서도 목표 지향적으로 이루어져서 일이 수월하게 처리되었다. 사회 경력이 별로 길지 않은 사람으로서, 주변 사람들에게서 코딩 외적으로도 배울 점이 많다는 것이 기뻤다.

아쉬운 점은 내가 그리 많은 도움을 드리지는 못했다는 점이었다. 내가 명시적으로 한 일은 지도 시각화 과정에서 각 대여장소별 반납 장소 TOP 10을 선정한 것 정도였다. 뭔가 노력과 삽질을 반복하기는 했는데, 결과물 면에서 많은 도움을 못 드린 게 아쉬웠다. 다음 프로젝트 때는 조금 더 효율적으로 결과물을 낼 수 있도록 노력해보는 게 좋을 것 같다.

profile
데이터 만지는 개발자를 향하여

0개의 댓글