본문 바로가기
Projects/⛴️ Ship Waiting Time Prediction

[선박 대기시간 예측] 시계열/선석 기반 EDA

by ISLA! 2023. 12. 15.

 

항만 대기시간 예측 및 운영시스템 개선을 위한  EDA

 

🎯 목표 : 시계열 데이터의 주기성을 확인하고, 시계열 예측 모델(Prophet)을 만들어 결과 확인하기 (데이터는 액체화물과 비액체화물로 나누어 진행)

liquid 데이터프레임

 

 

01.  연도별 월 별 대기시간 시각화(액체화물)

👉  목표 : 시간대별 대기시간 평균 / 건 수의 분포를 살펴 '시계열' 모델을 사용할 만 한 지 판단하기로 함

👉  결과 : 대기시간 평균은 뚜렷한 주기성은 보이지 않으나, 대기 건수는 월별로 편차가 있느 경향을 확인함

 

liquid['Datetime'] = pd.to_datetime(liquid['Datetime'])

# 월별 접안_대기시간_분(평균)
temp = liquid[['Datetime', 'ETA_Year','ETA_Month', '접안_대기시간_분']]
temp.head()

# 연도별로 데이터 분리하여 시각화
years = temp['ETA_Year'].unique()
yearly_data = [temp[temp['ETA_Year'] == year] for year in years]

plt.figure(figsize=(10, 6))

for year, data_year in zip(years, yearly_data):
    monthly_average = data_year.groupby(['ETA_Year', 'ETA_Month'])['접안_대기시간_분'].mean().reset_index()
    plt.plot(monthly_average['ETA_Month'], monthly_average['접안_대기시간_분'], marker='o', linestyle='-', label=str(year))

plt.title('연도별 월별 대기시간 평균(3년)')
plt.xlabel('월')
plt.ylabel('대기시간 평균 (분)')
plt.xticks(range(1, 13))
plt.legend(title='연도')
plt.grid(True)
plt.show()

 

 

# 연도별로 데이터 분리, 대기시간 건 수 비교
years = temp['ETA_Year'].unique()
yearly_data = [df[df['ETA_Year'] == year] for year in years]

plt.figure(figsize=(10, 6))

for year, data_year in zip(years, yearly_data):
    monthly_counts = data_year.groupby(['ETA_Year', 'ETA_Month']).size().reset_index(name='대기건수')
    plt.plot(monthly_counts['ETA_Month'], monthly_counts['대기건수'], marker='o', linestyle='-', label=str(year))
    
    
plt.title('월별 대기 건수')
plt.xlabel('월')
plt.ylabel('대기 건수')
plt.xticks(range(1, 13))
plt.legend(title='연도')
plt.grid(True)
plt.show()

 

 

02.  연도 별 주 별 대기시간 시각화(액체화물)

👉  결과 : 대기시간 평균은 뚜렷한 주기성은 보이지 않으나, 대기 건수는 월별 시각화에서 확인한 경향과 유사하게 특정 주간에 낮은 경향을 확인함

# Datetime 열을 날짜와 시간으로 분리 >> 주 별 데이터
df = temp.copy()
df['Date'] = pd.to_datetime(df['Datetime']).dt.date

# 주차 정보 추가
df['주차'] = pd.to_datetime(df['Date']).dt.strftime('%U').astype(int) + 1

# 연도별로 데이터 분리
years = df['ETA_Year'].unique()
yearly_data = [df[df['ETA_Year'] == year] for year in years]

# 시각화
plt.figure(figsize=(12, 6))

for year, data_year in zip(years, yearly_data):
    weekly_average = data_year.groupby(['ETA_Year', '주차'])['접안_대기시간_분'].mean().reset_index()
    plt.plot(weekly_average['주차'], weekly_average['접안_대기시간_분'], marker='o', linestyle='-', label=str(year))

plt.title('연도별 주(Week)별 대기시간 평균')
plt.xlabel('주(Week)')
plt.ylabel('대기시간 평균 (분)')
plt.legend(title='연도')
plt.grid(True)
plt.show()

 

 

# Datetime 열을 날짜와 시간으로 분리 >> >> 3개년 주 별 대기시간 건 수 계산
df = temp.copy()
df['Date'] = pd.to_datetime(df['Datetime']).dt.date

# 주차 정보 추가
df['주차'] = pd.to_datetime(df['Date']).dt.strftime('%U').astype(int) + 1

# 연도별로 데이터 분리
years = df['ETA_Year'].unique()
yearly_data = [df[df['ETA_Year'] == year] for year in years]

# 시각화
plt.figure(figsize=(12, 6))

for year, data_year in zip(years, yearly_data):
    weekly_average = data_year.groupby(['ETA_Year', '주차'])['접안_대기시간_분'].size().reset_index(name='대기건수')
    plt.plot(weekly_average['주차'], weekly_average['대기건수'], marker='o', linestyle='-', label=str(year))

plt.title('연도별 주(Week)별 대기시간 건수')
plt.xlabel('주(Week)')
plt.ylabel('대기시간 건수 (개)')
plt.legend(title='연도')
plt.grid(True)
plt.show()

 

 

03.  시간대별 접안 대기시간 시각화

👉  목표 : 시간대(하루 중 어느 시점)에 따라 대기가 더 길게 발생하는지에 대한 확인이 필요함

👉  결과 : 하루 중 특정 시점이 눈에 띄게 높거나 낮는 등의 차이 없음

cols = ['ETA_Hour', '접안_대기시간_분']
temp02 = liquid[cols]
temp02.head()

hour_mean = temp02.groupby('ETA_Hour').mean()

plt.figure(figsize=(30, 6))
plt.bar(hour_mean.index, hour_mean['접안_대기시간_분'])
plt.xlabel('시간대')
plt.ylabel('평균 대기시간(분)')
plt.title('시간대별 대기시간 평균 시각화')
# plt.xticks(rotation=45)
plt.xticks(hour_mean.index)
plt.show()

 

 

 

04.  계선장소별(선석) 대기시간 평균 시각화

👉  목표 : 선석별 3개년 대기시간 평균 시각화를 통해 선석별로 대기시간에 차이가 있는지 확인하고자 함

👉  결과 : 접안지(대기용)의 대기시간이 높으며 큰 차이가 없음

 

# 계선장소 코드/숫자 기준, 일자별 접안대기시간 정리
temp01 = liquid[['Datetime', '계선장소_코드', '계선장소_숫자', '접안_대기시간_분']]
temp01['계선장소'] = temp01['계선장소_코드'] + '_' + temp01['계선장소_숫자'].astype(str)

temp01.drop(columns = ['계선장소_코드', '계선장소_숫자'], inplace = True)
temp01.head(3)

# 계선장소별 대기시간 평균 계산
average_wait_time = temp01.groupby('계선장소')['접안_대기시간_분'].mean().reset_index().sort_values(by = '접안_대기시간_분', ascending = False).head(20)

# 시각화
plt.figure(figsize=(30, 6))
plt.bar(average_wait_time['계선장소'], average_wait_time['접안_대기시간_분'])
plt.xlabel('계선장소')
plt.ylabel('평균 대기시간(분)')
plt.title('계선장소별 대기시간 평균 시각화')
plt.xticks(rotation=45)
plt.show()

 

728x90