관리 메뉴

솜씨좋은장씨

설날 귀성/귀경시간을 예측해보자! - 01 데이터 수집 및 시각화를 통한 최적, 혼잡시간대 추측해보기 본문

Programming/Python

설날 귀성/귀경시간을 예측해보자! - 01 데이터 수집 및 시각화를 통한 최적, 혼잡시간대 추측해보기

솜씨좋은장씨 2020. 1. 14. 16:14
728x90
반응형

사진출처

 

"언제 출발할까"…T맵·카카오내비 추석 교통 예측

【서울=뉴시스】이진영 기자 = 추석 연휴(9월 12~15일)를 앞두고 길 안내 내비게이션 서비스를 운영하는 SK텔레콤과 카카오가 귀성·귀경길 교통 예측 결과를 발표했다

www.newsis.com

 

 

2019년 추석

 

T맵을 운영하고 있는 SKT와 카카오네비를 운영하고 있는 KAKAO에서 지난 5년간 축적된 빅데이터를 분석하여

 

귀성/귀경 시간을 예측하여 정보를 공개한 것을 보고 저도

 

고속도로 주요 톨게이트 사이의 소요시간 데이터를 모아 그래프를 그려 추측해본 적이 있었습니다.

 

 

[Python]과거의 데이터로 최적의 추석 귀경시간 추측해보기(feat, matplotlib)

2년의 데이터를 가지고 도출한 최적의 귀경시간 본 표에 적혀있는 시간은 그저 받아온 데이터를 그래프로 그리고 눈으로 확인해보며 선정한 시간입니다. 만약에 보시게 된다면 재미로 참고만 하시기 바랍니다~ 출..

somjang.tistory.com

아쉬웠던 점은 추석이 끝나가는 시점이어서 추석 1일 후, 2일 후의 귀경시간만 확인해보았고

 

아직 머신러닝/딥러닝을 활용하여 모델링을 해본 적이 없었기에

 

예측까지는 해보지 못하고 그래프를 그려 추측만 해보았던 점이 아쉬웠습니다.

 

다음 설날을 기약하며 글을 마쳤었습니다.

 

드디어 2020년 설날!

 

드디어 기약하던 설날이 코앞으로 다가왔습니다.

 

올해의 목표는!

 

과거 설날 데이터를 가지고

 

1. 데이터를 수집하여 그래프를 그려 데이터를 비교 해보는 것에 더불어 머신러닝/딥러닝을 활용하여 시계열 예측을 해보고

 

2. 카카오, SKT에서 예측한 데이터와 비교

 

3. 실제 소요시간과의 비교

 

해보는 것을 목표로 삼아보았습니다.

 

 

<2018년 데이터로 추측해본 2020년 귀성/귀경길 혼잡, 최적 시간대>

평일/휴일 비율이 비슷한 2018년 설 연휴의 데이터를 가지고 추측해본 시간대입니다.

< 데이터 수집 >

먼저 지난 추석에 데이터를 수집했던 방법에서 변수만 바꾸어 설날때의 데이터를 받아왔습니다.

 

[Python]지난 2년간의 추석 귀경길 도시 구간별 소요시간 파이썬으로 데이터 받아보기

[Python]과거의 데이터로 최적의 추석 귀경시간 추측해보기(feat, matplotlib) 2년의 데이터를 가지고 도출한 최적의 귀경시간 본 표에 적혀있는 시간은 그저 받아온 데이터를 그래프로 그리고 눈으로 확인해보며..

somjang.tistory.com

귀경 소요시간

def getgoUpTimeData(startPageNo, endPageNo, Year):
  info_df_daegeon = pd.DataFrame(columns=["출발지", "기준시간", str(Year)+"소요시간"])
  info_df_daegu = pd.DataFrame(columns=["출발지", "기준시간", str(Year)+"소요시간"])
  info_df_busan = pd.DataFrame(columns=["출발지", "기준시간", str(Year)+"소요시간"])
  info_df_gwangju = pd.DataFrame(columns=["출발지", "기준시간", str(Year)+"소요시간"])
  info_df_ganglung = pd.DataFrame(columns=["출발지", "기준시간", str(Year)+"소요시간"])
  info_df_mockpo = pd.DataFrame(columns=["출발지", "기준시간", str(Year)+"소요시간"])

  daegeon = 0
  daegu = 0
  busan = 0
  gwangju = 0
  ganglung = 0
  mockpo = 0



  for pageNo in range(startPageNo, endPageNo):
    startPoints = []
    stdTimes = []
    timeTOGOs = []

    url = 'http://data.ex.co.kr/openapi/specialAnal/intercityLeadTime'
    parameters = {"key":"test", "type":"xml", "numOfRows":"24", "pageNo":str(pageNo), "iYear":str(Year)}
    req = requests.get(url, params=parameters)

    xml_data = xmltodict.parse(req.text)
    infomations = xml_data['data']['intercityLeadTimeLists']

    for info in infomations:
      if info['dirNm'] == '귀경방향':
        if info['stUnitNm'] == "대전":
          info_df_daegeon.loc[daegeon] = [info['stUnitNm'], info['stdHour'], float(info['trtm'][0:5])]
          daegeon = daegeon + 1
        elif info['stUnitNm'] == "대구":
          info_df_daegu.loc[daegu] = [info['stUnitNm'], info['stdHour'], float(info['trtm'][0:5])]
          daegu = daegu + 1
        elif info['stUnitNm'] == "부산":
          info_df_busan.loc[busan] = [info['stUnitNm'], info['stdHour'], float(info['trtm'][0:5])]
          busan = busan + 1
        elif info['stUnitNm'] == "광주":
          info_df_gwangju.loc[gwangju] = [info['stUnitNm'], info['stdHour'], float(info['trtm'][0:5])]
          gwangju = gwangju + 1
        elif info['stUnitNm'] == "강릉":
          info_df_ganglung.loc[ganglung] = [info['stUnitNm'], info['stdHour'], float(info['trtm'][0:5])]
          ganglung = ganglung + 1
        elif info['stUnitNm'] == "목포":
          info_df_mockpo.loc[mockpo] = [info['stUnitNm'], info['stdHour'], float(info['trtm'][0:5])]
          mockpo = mockpo + 1
  return (info_df_daegeon, info_df_daegu, info_df_busan, info_df_gwangju, info_df_ganglung, info_df_mockpo)

귀성 소요시간

def getgoDownTimeData(startPageNo, endPageNo, Year):
  info_df_daegeon = pd.DataFrame(columns=["도착지", "기준시간", str(Year)+"소요시간"])
  info_df_daegu = pd.DataFrame(columns=["도착지", "기준시간", str(Year)+"소요시간"])
  info_df_busan = pd.DataFrame(columns=["도착지", "기준시간", str(Year)+"소요시간"])
  info_df_gwangju = pd.DataFrame(columns=["도착지", "기준시간", str(Year)+"소요시간"])
  info_df_ganglung = pd.DataFrame(columns=["도착지", "기준시간", str(Year)+"소요시간"])
  info_df_mockpo = pd.DataFrame(columns=["도착지", "기준시간", str(Year)+"소요시간"])

  daegeon = 0
  daegu = 0
  busan = 0
  gwangju = 0
  ganglung = 0
  mockpo = 0



  for pageNo in tqdm(range(startPageNo, endPageNo)):
    startPoints = []
    stdTimes = []
    timeTOGOs = []

    url = 'http://data.ex.co.kr/openapi/specialAnal/intercityLeadTime'
    parameters = {"key":"test", "type":"xml", "numOfRows":"24", "pageNo":str(pageNo), "iYear":str(Year)}
    req = requests.get(url, params=parameters)

    xml_data = xmltodict.parse(req.text)
    infomations = xml_data['data']['intercityLeadTimeLists']
    # print(infomations)

    for info in infomations:
      if info['dirNm'] == '귀성방향':
        if info['edUnitNm'] == "대전":
          info_df_daegeon.loc[daegeon] = [info['edUnitNm'], info['stdHour'], float(info['trtm'][0:5])]
          daegeon = daegeon + 1
        elif info['edUnitNm'] == "대구":
          info_df_daegu.loc[daegu] = [info['edUnitNm'], info['stdHour'], float(info['trtm'][0:5])]
          daegu = daegu + 1
        elif info['edUnitNm'] == "부산":
          info_df_busan.loc[busan] = [info['edUnitNm'], info['stdHour'], float(info['trtm'][0:5])]
          busan = busan + 1
        elif info['edUnitNm'] == "광주":
          info_df_gwangju.loc[gwangju] = [info['edUnitNm'], info['stdHour'], float(info['trtm'][0:5])]
          gwangju = gwangju + 1
        elif info['edUnitNm'] == "강릉":
          info_df_ganglung.loc[ganglung] = [info['edUnitNm'], info['stdHour'], float(info['trtm'][0:5])]
          ganglung = ganglung + 1
        elif info['edUnitNm'] == "목포":
          info_df_mockpo.loc[mockpo] = [info['edUnitNm'], info['stdHour'], float(info['trtm'][0:5])]
          mockpo = mockpo + 1
  return (info_df_daegeon, info_df_daegu, info_df_busan, info_df_gwangju, info_df_ganglung, info_df_mockpo)

2019년 설날

날짜 도시 순서 numOfRows pageNo
설날 3일전 (D-3) 귀성길 대전, 대구, 부산, 광주, 강릉 목포 24 48 ~ 54
설날 3일전 (D-3) 귀경길 대전, 대구, 부산, 광주, 강릉, 목포 24 54 ~ 60
설날 2일전 (D-2) 귀성길 대전, 대구, 부산, 광주, 강릉, 목포 24 60 ~ 66
설날 2일전 (D-2) 귀경길 대전, 대구, 부산, 광주, 강릉, 목포 24 66 ~ 71
설날 1일전 (D-1) 귀성길 대전, 대구, 부산, 광주, 강릉, 목포 24 71 ~ 77
설날 1일전 (D-1) 귀경길 대전, 대구, 부산, 광주, 강릉, 목포 24 77 ~ 83
설날 당일 (D) 귀성길 대전, 대구, 부산, 광주, 강릉, 목포 24 83 ~ 89
설날 당일 (D) 귀경길 대전, 대구, 부산, 광주, 강릉, 목포 24 89 ~ 95
설날 1일후 (D+1) 귀성길 대전, 대구, 부산, 광주, 강릉, 목포 24 95 ~ 101
설날 1일후 (D+1) 귀경길 대전, 대구, 부산, 광주, 강릉, 목포 24 101 ~ 107
설날 2일후(D+2) 귀성길 대전, 대구, 부산, 광주, 강릉, 목포 24 107 ~ 113
설날 2일후(D+2) 귀경길 대전, 대구, 부산, 광주, 강릉, 목포 24 113 ~ 119
설날 2일후(D+3) 귀성길 대전, 대구, 부산, 광주, 강릉, 목포 24 119 ~ 125
설날 2일후(D+3) 귀경길 대전, 대구, 부산, 광주, 강릉, 목포 24 125 ~ 131

2018년 설날

날짜 도시 순서 numOfRows pageNo
설날 3일전 (D-3) 귀성길 대전, 대구, 부산, 광주, 강릉 목포 24 48 ~ 54
설날 3일전 (D-3) 귀경길 대전, 대구, 부산, 광주, 강릉, 목포 24 54 ~ 60
설날 2일전 (D-2) 귀성길 대전, 대구, 부산, 광주, 강릉, 목포 24 60 ~ 66
설날 2일전 (D-2) 귀경길 대전, 대구, 부산, 광주, 강릉, 목포 24 66 ~ 72
설날 1일전 (D-1) 귀성길 대전, 대구, 부산, 광주, 강릉, 목포 24 72 ~ 78
설날 1일전 (D-1) 귀경길 대전, 대구, 부산, 광주, 강릉, 목포 24 78 ~ 84
설날 당일 (D) 귀성길 대전, 대구, 부산, 광주, 강릉, 목포 24 84 ~ 90
설날 당일 (D) 귀경길 대전, 대구, 부산, 광주, 강릉, 목포 24 90 ~ 96
설날 1일후 (D+1) 귀성길 대전, 대구, 부산, 광주, 강릉, 목포 24 96 ~ 102
설날 1일후 (D+1) 귀경길 대전, 대구, 부산, 광주, 강릉, 목포 24 102 ~ 108
설날 2일후(D+2) 귀성길 대전, 대구, 부산, 광주, 강릉, 목포 24 108 ~ 114
설날 2일후(D+2) 귀경길 대전, 대구, 부산, 광주, 강릉, 목포 24 114 ~ 120
설날 2일후(D+3) 귀성길 대전, 대구, 부산, 광주, 강릉, 목포 24 120 ~ 126
설날 2일후(D+3) 귀경길 대전, 대구, 부산, 광주, 강릉, 목포 24 126 ~ 132

 

설날 기간으로 제공되는 데이터는 작년 추석과 마찬가지로 2018년, 2019년 총 2년치의 데이터를 얻을 수 있었습니다.

 

< 수집한 데이터 그래프로 시각화 해보기>

작년과 마찬가지로 수집한 데이터를 그래프로 시각화 하여 확인해보았습니다.

def drawGraph(data_df_2018, data_df_2019, day, updown):
  plt.rcParams['figure.figsize'] = (15, 8)

  if updown == 0:
    ax = data_df_2018.plot.line()
    ax1 = data_df_2019.plot.line(ax = ax, grid=True)
    ax1.set_title("2018년 / 2019년 설날 " + day +" 시간별 "+ "(" + data_df_2019.loc[0]['출발지'] +" -> 서울) 소요시간", size=25)
    ax1.set_xticks(list(range(0,24)))
    ax1.set_xlabel("시간 (00시~23시)", size=20)
    ax1.set_ylabel('소요시간 (분)', size=20)
  else:
    ax = data_df_2018.plot.line()
    ax1 = data_df_2019.plot.line(ax = ax, grid=True)
    ax1.set_title("2018년 / 2019년 설날 " + day +" 시간별 "+ "( 서울 -> " + data_df_2019.loc[0]['도착지'] +") 소요시간", size=25)
    ax1.set_xticks(list(range(0,24)))
    ax1.set_xlabel("시간 (00시~23시)", size=20)
    ax1.set_ylabel('소요시간 (분)', size=20)

 

 

1. 서울에서 대전까지 소요시간

서울 -> 대전 설날 3일 전 / 2일 전 / 1일 전

서울 -> 대전 설날 당일

서울 -> 대전 설날 1일 후 / 2일 후 / 3일 후

 

2. 서울에서 대구까지 소요시간

서울 -> 대구 설날 3일 전 / 2일 전 / 1일 전

서울 -> 대구 설날 당일

서울 -> 대구 설날 1일 후 / 2일 후 / 3일 후

 

3. 서울에서 부산까지 소요시간

서울 -> 부산 설날 3일 전 / 2일 전 / 1일 전

서울 -> 부산 설날 당일

서울 -> 부산 설날 1일 후 / 2일 후 / 3일 후

 

4. 서울에서 광주까지 소요시간

서울 -> 광주 설날 3일 전 / 2일 전 / 1일 전

서울 -> 광주 설날 당일

서울 -> 광주 설날 1일 후 / 2일 후 / 3일 후

 

5. 서울에서 강릉까지 소요시간

서울 -> 강릉 설날 3일 전 / 2일 전 / 1일 전

서울 -> 강릉 설날 당일

서울 -> 강릉 설날 1일 후 / 2일 후 / 1일 후

 

6. 서울에서 목포까지 소요시간

서울 -> 목포 설날 3일 전 / 2일 전 / 1일 전

서울 -> 목포 설날 당일

서울 -> 목포 설날 1일 후 / 2일 후 / 1일 후

 

7. 대전에서 서울까지 소요시간

대전 -> 서울 설날 3일 전 / 2일 전 / 1일 전

대전 -> 서울 설날 당일

대전 -> 서울 설날 1일 후 / 2일 후 / 3일 후

 

8. 대구에서 서울까지 소요시간

대구 -> 서울 설날 3일 전 / 2일 전 / 1일 전

대구 -> 서울 설날 당일

대구 -> 서울 설날 1일 후 / 2일 후 / 3일 후

 

9. 부산에서 서울까지 소요시간

부산 -> 서울 설날 3일 전 / 2일 전 / 1일 전

부산 -> 서울 설날 당일

부산 -> 서울 설날 1일 후 / 2일 후 / 3일 후

 

10. 광주에서 서울까지 소요시간

광주 -> 서울 설날 3일 전 / 2일 전 / 1일 전

광주 -> 서울 설날 당일

광주 -> 서울 설날 1일 후 / 2일 후 / 3일 후

 

11. 강릉에서 서울까지 소요시간

강릉 -> 서울 설날 3일 전 / 2일 전 / 1일 전

강릉 -> 서울 설날 당일

강릉 -> 서울 설날 1일 후 / 2일 후 / 3일 후

 

12. 목포에서 서울까지 소요시간

목포 -> 서울 설날 3일 전 / 2일 전 / 1일 전

목포 -> 서울 설날 당일

목포 -> 서울 설날 1일 후 / 2일 후 / 3일 후

 

<과거의 데이터를 가지고 최적의 시간 추측해보기> 

2018년 설날 연휴

  2일 전 1일전 당일 1일 후 2일 후
날짜 / 요일

2018년 2월 14일

수요일

2018년 2월 15일

목요일

2018년 2월 16일

금요일

2018년 2월 17일

토요일

2018년 2월 18일

일요일

2019년 설날 연휴

  2일 전 1일전 당일 1일 후 2일 후
날짜 / 요일

2019년 2월 3일

일요일

2019년 2월 4일

월요일

2019년 2월 5일

화요일

2019년 2월 6일

수요일

2019년 2월 7일

목요일

2020년 설날 연휴

  2일 전 1일전 당일 1일 후 2일 후
날짜 / 요일

2020년 1월 24일

목요일

2020년 1월 25일

금요일

2020년 1월 26일

토요일

2020년 1월 27일

일요일

2020년 1월 28일

월요일 (대체)

2020년의 설날 연휴는 평일/휴일의 배치가 2018년과 유사한 것을 볼 수 있습니다.

 

이에 시각화를 통한 도시간 이동에 소요시간이 가장 적게 드는

최적의 시간 추측은 2018년 데이터를 기준으로 

설날 당일 2일 전 / 2일 후 이 5일 동안의 데이터에서

 

서울에서 지방으로 내려가는 귀성길은 설날 2일전 ~ 당일

지방에서 서울로 올라가는 귀경길은 설날 당일 ~ 2일 데이터를 가지고 

당시에 가장 소요시간이 많이 걸린 시간과 적게 걸린 시간을 찾아 추측해보았습니다.

 

사용 코드

def findGoodTimeToGo(data_before2, data_before1, data_Dday, data_after1, data_after2, index, UpDown):
  data_before2['DAY'] = ['BEFORE2'] * len(data_before2['2018소요시간'])
  data_before1['DAY'] = ['BEFORE1'] * len(data_before1['2018소요시간'])
  data_Dday['DAY'] = ['DDAY'] * len(data_Dday['2018소요시간'])
  data_after1['DAY'] = ['AFTER1'] * len(data_after1['2018소요시간'])
  data_after2['DAY'] = ['AFTER2'] * len(data_after2['2018소요시간'])

  if UpDown == 1:
    before2_1_Dday = pd.concat([data_before2, data_before1, data_Dday])

    new_index = []
    for i in range(len(before2_1_Dday)):
      new_index.append(i)
    before2_1_Dday.index = new_index

    time_list = list(before2_1_Dday['2018소요시간'])

    min_time = min(time_list)
    max_time = max(time_list)


    indexs = []
    for i in range(len(before2_1_Dday['2018소요시간'])):
      if before2_1_Dday['2018소요시간'].iloc[i] == min_time:
        indexs.append(i)
      elif before2_1_Dday['2018소요시간'].iloc[i] == max_time:
        indexs.append(i)
    temp_df = before2_1_Dday.loc[indexs]

  elif UpDown == 0:
    Dday_after1_2 = pd.concat([data_Dday, data_after1, data_after2])

    new_index = []
    for i in range(len(Dday_after1_2)):
      new_index.append(i)
    Dday_after1_2.index = new_index

    time_list = list(Dday_after1_2['2018소요시간'])

    min_time = min(time_list)
    max_time = max(time_list)

    indexs = []
    for i in range(len(Dday_after1_2['2018소요시간'])):
      if Dday_after1_2['2018소요시간'].iloc[i] == min_time:
        indexs.append(i)
      elif Dday_after1_2['2018소요시간'].iloc[i] == max_time:
        indexs.append(i)
    temp_df = Dday_after1_2.loc[indexs]
    
  return temp_df

앞으로 추가로 데이터를 수집하여 머신러닝/딥러닝을 활용하여 예측을 해보고자 합니다.

 

읽어주셔서 감사합니다~

Comments