데이터 생존 로그

3000번 버스, 탈 수 있을까? - 데이터 기반으로 퇴근시간 정하기 본문

📊 분석 한 스푼 🥄

3000번 버스, 탈 수 있을까? - 데이터 기반으로 퇴근시간 정하기

분석가 베어그릴스 2025. 3. 1. 21:33

배경

나는 수원 - 강남을 통근하는 통근러이다.

매주 출근일마다 편도 100분 가량 걸리는 거리를 3000번 버스와 함께 통근한다.

 

아주 춥던 어느 날, 퇴근 버스를 놓치고 말았다.

요즘 광역 버스는 입석이 안되고, 내 앞앞에서 잔여 좌석이 0석이 되어 강제로 타지 못하고 말았다,,,

 

그래서 시작했다.

언제 퇴근을 해야 내가 안전하게 버스를 타고 집에 갈 수 있을 지를 데이터 기반으로 찾아보기로!

 

데이터 수집

내가 모으고자 하는 데이터는 깊게 생각치 않았다.

 

여러 지도 플랫폼에서 제공하는 버스 위치/잔여 좌석 데이터의 스냅샷을 

최대한 '짧은 주기'로 모으면 만사 OK라고 생각했다.

 

 

내가 얻고자 하는 버스 데이터는 '공공 데이터 포털'의 OPEN API와 

요즘 내가 요리조리 써 먹고 있는 'N8N'이라는 자동화 툴을 활용해 스프레드시트에 적재했다. (아래 게시글 참고)

https://analyst-ggom-chi-kim.tistory.com/27

 

간단히 파이프라인을 소개하면,

 

매 3분 마다 trigger가 실행된다.

공공 데이터 포털의 일일 api 수를 고려하여 최대한 촘촘하게(자주) 데이터를 수집하려 했고, 그 기준이 대략 3분 정도 였다.

 

만약 시간대가 2~5시 사이라면, 적재하지 않는다. (어차피 그 때 시간의 정보는 필요 없으니까)

 

api를 통해 호출한 후, 간단한 전처리를 하면 다음과 같은 컬럼 명세를 갖는 데이터가 쌓인다.

컬럼명 description example
plateNo 버스 번호판 경기70사1642
remainSeatCnt 잔여 좌석 35
stationId 정류장 번호 220000137
stationSeq 정류장 순서 52
timestamp 데이터 수집 시간 2025-02-08 16:12:36

 

위 데이터를 약 2주 간 적재했다.

 

추가로, 정류장 이름을 매핑시켜주기 위해 다음 데이터도 찾아서 저장해 두었다.

컬럼명 description example
stationId 정류장 번호 220000137
stationName 정류장 이름 선바위역2번출구(광역)
stationSeq 정류장 순서 52

 

데이터 전처리

간단한 과정(pandas merge)을 통해 수집된 스냅샷 데이터에 정류장 이름을 매핑해 줄 수 있었다.

 

하지만 그 이후 문제가 하나 발생했다.

'각 버스의 고유한 운행 정보를 모른다는 것!'

 

예를 들어, 경기70사1642 버스는 3분 마다 정류장과 잔여 좌석 정보가 찍힐텐데, 만약 같은 정류장에 두 번 찍혔다면 그걸 구분할 방법이 없다는 것이었다.

 

단순히 날짜와 버스 번호판(경기70사1642)을 concat시켜서 unique한 개수를 센다고 해서 해결될 문제가 아니었다.

(왜냐면 경기70사1642 버스는 하루에도 여러 번 운행할 수 있기 때문..)

 

그래서 다음과 같이 각 row별로 trip_id를 달아주기로 했다.

1. 재시작(restart) 정의: 시간은 더 큰 값을 갖는데, stationSeq가 더 작다면, 버스가 종점 도착 후 재시작했다고 판단할 수 있다.

2. 운행 id(trip_id) 정의: 해당 날짜와 앞서 정의한 재시작의 '누적값'을 concat하면 unique한 운행을 정의할 수 있다!

 

trip_id는 하나의 고유한 운행으로 정의할 수 있다.

이제 원하는 시간대별로 aggregation한 다음, 원하는 조건에 따라 unique한 trip_id를 집계만 하면 된다!

 

분석 & 시각화

시각화는 간단히 해낼 수 있다.

  • 특정 정류장으로 필터링 한 후
  • 5분 단위로 aggregation 한다.
    • unique한 trip_id의 수는 해당 시간대에 운행한 버스 수를 의미한다.
    • 잔여좌석이 5건 이하인 unique한 trip_id의 수는 해당 시간대에 놓칠 위험이 있는 버스 수를 의미한다. 

 

실제로 데이터를 보면 다음과 같다.

 

당연하겠지만, 퇴근시간인 오후5~7시 사이에 놓칠 위험이 있는 버스가 많이 운행된 것을 볼 수 있다.

 

조금 더 zoom-in 하여 살펴보면,

 

18:35분(그림 상 1)과 19:00(그림 상 2)가 위험해 보인다.

특히, 18:35분에 타면 100% 확률로 잔여좌석 5석 이하가 남아버린다.

 

위 간단한 집계를 통해 다음 결론에 다다를 수 있겠다!

  • 엥간하면 18:35에는 집에 가지 말자..
  • 19:00도 마찬가지
  • 그 언저리에 집에 가려면 18:40 쯤이 적당해 보인다!

 

아! 시각화 한 게 아까우니 streamlit에 올려두도록 하겠다. 😉

https://can-i-take-bus.streamlit.app/

 

🚌 3000번 버스 탈 수 있을까?

This app was built in Streamlit! Check it out and visit https://streamlit.io for more awesome community apps. 🎈

can-i-take-bus.streamlit.app

 

 

 

반응형
Comments