끄적끄적

CH 2. 기초 프로젝트 - 데이터 분석 (1) 본문

[스파르타]내일배움캠프 데이터 분석 트랙/Project

CH 2. 기초 프로젝트 - 데이터 분석 (1)

kminx 2025. 6. 17. 22:02

사용하는 데이터

더보기
닫기

데이터 출처: 

https://www.kaggle.com/datasets/gauravmalik26/food-delivery-dataset/data?select=train.csv

 

테이블 설명: 

컬럼명 설명 데이터 타입
ID 주문 건 ID object
Delivery_person_ID Delivery Person 고유 ID object
Delivery_person_Age Delivery Person 나이 object
Delivery_person_Ratings Delivery Person 평점 (1 to 5) object
Restaurant_latitude Restaurant 위도 float64
Restaurant_latitude Restaurant 경도 float64
Delivery_location_latitude 배달 목적지 위도 float64
Delivery_location_longitude 배달 목적지 경도 float64
Order_Date 주문 날짜 object
Time_Ordered 주문 시간 object
Time_Order_picked 배달원이 음식 픽업한 시간 object
Weather conditions 기상상태 (Windy, Sunny, Cloudy, Stormy, Fog, Sandstoms 등) object
Road_traffic_density 배달 당시 도로 교통 상황 (Jam, High, Medium, Low) object
Vehicle_condition 배달 차량의 상태 (Smooth, good, average) int64
Type_of_order 배달음식 종류 (Snack, Meal, Buffet, Drinks 등) object
Type_of_vehicle 배달 차량 종류 (motorbike, bicycle 등) object
multiple_deliveries 한 번에 배달원이 배당받은 배달 건수 object
Festival 당일에 축제가 있는지 여부 object
City 배달지역 도시화 정도 (Metropolitian, Urban 등) object
Time_taken(min) 배달에 걸린 시간 (분 단위) object

 

2025.06.13 - [[스파르타]내일배움캠프 데이터 분석 트랙] - 23일차 - 기초 프로젝트 데이터 전처리


1. 데이터 분포 파악

먼저 각 데이터들의 타입이 어떤지, 분포가 어떻게 되는지를 파악했다.

전처리를 수행한 최종 데이터의 컬럼 수는 25개이며, 그중 새롭게 추가한 칼럼이 5개이다.

추가로 데이터 분석을 쉽게 수행하기 위해서 주문 시각, 주문한 달 칼럼을 추가했다.

 

전체 컬럼의 데이터 타입을 살펴보면 크게 float, int, object, datetime 이렇게 4가지가 존재한다.

 

이 중 unique 값이 너무 많은 일부를 제외하고, 데이터 분포를 살펴보았다.

더보기
# 분포 그래프 예시
import matplotlib.pyplot as plt

col_name = ['Weatherconditions', 'Road_traffic_density', 'Type_of_order', 'Type_of_vehicle','Vehicle_condition','multiple_deliveries','Festival','City']

fig, axes = plt.subplots(nrows=2, ncols=4, figsize=(16, 6)) 
axes = axes.flatten()

for i,c in enumerate(col_name):
    sns.countplot(data=df, x=c, ax = axes[i])
    axes[i].set_title(f'{c}')
    axes[i].set_ylabel('Counts')
    axes[i].tick_params(axis='x', rotation=45)

plt.tight_layout()
plt.show()

 

데이터 분포를 통해 얻을 수 있는 정보는

1. 날씨와 상관없이 배달 건수는 비슷하다.

2. 음식 종류는 비슷하게 배달되었다.

3. 오토바이를 이용한 배달 건수가 가장 많다.

4. 배달 차량의 상태는 비슷하다.

5. 배달량은 한번에 2건 배달이 가장 많고, 그다음으로 단건 배달이 많다.

6. 축제가 열리지 않은 날에 배달이 더 잦다.

7. 주로 metropolitian인 지역에서 배달을 많이 시켰다. (urban과 metropolitian 차이)

8. 주말보다 주중에 배달 주문이 많다 (그러나, 주중은 5일이고 주말은 2일이니 그것도 고려)

9. 저녁 시간대의 주문건수가 많아진다.

10. 데이터는 2월, 3월, 4월의 배달 데이터이며, 3월 배달건이 가장 많다. (2022년 기준은 미리 확인했다.)

 

추가로 잘 안 보이는 'Time_taken(min)'을 크게 보면, 15분에서 29분 사이의 배달 건수가 가장 많다.

 

 

2. 피어슨 상관계수를 사용한 히트맵 그리기

수치형 데이터를 대상으로 피어슨 상관계수를 사용한 히트맵을 그려보았다.

import seaborn as sns
import matplotlib.pyplot as plt 

# 수치형 데이터만
df_num = df.select_dtypes(include=['int64','float64','int32'])
tcorr = df_num.corr()

plt.figure(figsize=(8,6))
sns.heatmap(tcorr, annot=True, fmt='.2f', cmap='vlag', center=0)
plt.title('heatmap')
plt.show()

그러나, 눈에 확 보이는 상관계수는 보이지 않기 때문에 차근히 하나의 칼럼씩 살펴보고자 한다.

 

3. 가설 세우기

본격적으로 분석을 시작하기 전에 어떤 컬럼이 배달 시간에 영향을 미칠지 미리 가설을 세워보았다.

 

배달 기사 기준

  • 나이 vs 배달 시간: 배달 기사의 나이가 많아질수록 배달 소요 시간이 달라질 것이다.
  • 평점 vs 배달 시간: 평점이 높은 배달 기사가 더 빠르게 배달할 것이다.
  • 나이 vs 평점: 배달 기사의 나이가 평점에 영향을 미칠 것이다.
  • 동시 배달 건수 vs 배달 시간: 동시 배달 건수가 많아질수록 배달 소요 시간이 증가할 것이다.

배달 차량 기준

  • 차량 종류 vs 배달 시간: 오토바이가 스쿠터보다 평균 배달 시간이 짧을 것이다.
  • 차량 상태 vs 배달 시간: 차량 상태가 좋을수록 배달 시간이 짧을 것이다.

주문 날짜·시각 기준

  • 시간대 vs 배달 시간: 교통 혼잡 시간대(점심·퇴근)에 배달 시간이 더 길 것이다.
  • 요일 vs 배달 시간: 주말(토·일)에 배달 시간이 더 길 것이다.
  • 주중/주말 vs 배달 시간: 주말 평균 배달 시간이 주중보다 유의하게 길 것이다.
  • 주말·시간대 상호작용: 주말 점심·저녁 피크에 배달 시간이 특히 더 늘어날 것이다.

배달 물품·거리·위치 기준

  • 배달 물품 종류 vs 배달 시간: 품목이 간단한 배달의 배달 시간이 더 길 것이다.
  • 배달 거리 vs 배달 시간: 거리가 증가할수록 배달 시간이 늘어날 것이다.
  • 배달 위치 vs 배달 시간: 도심 외곽 지역의 배달 시간이 더 길 것이다.
  • 도시화 정도 vs 배달 소요: 같은 위치라도 도시화 정도에 따라 배달 시간이 차이 날 것이다.

외부 요인

  • 동시 배달 건수·배달지 상호작용: 도심에서 동시 배달 건수가 많으면 배달 시간이 더욱 길어질 것이다.
  • 축제 유무 vs 배달 시간: 축제 기간에 배달 시간이 유의하게 늘어날 것이다.
  • 축제·교통 상황 상호작용: 축제 기간 교통 혼잡도가 높아 배달 시간이 더 늘어날 것이다.
  • 날씨·교통 상황 상호작용: 날씨에 따라 교통 혼잡도가 높아 배달 시간이 더 늘어날 것이다.
  • 시간대·교통 상황 상호작용: 퇴근 시간대 교통 상황이 나쁘면 배달 시간이 크게 증가할 것이다.
  • 요일·교통 상황 상호작용: 특정 요일(예: 금요일) 교통 체증이 심할 때 배달 시간이 더 늘어날 것이다.

 

4. 배달 기사 기준

배달 기사의 나이, 평점, 배달 건수에 따른 산점도를 통해 배달 시간과의 상관관계를 파악해보았다. 

또한, 배달 기사의 나이가 평점에 영향을 미치는지도 확인해보았다.

 

이렇게 산점도를 확인했을 때는 딱히 상관 관계를 확인하기 힘들어, 각 변수를 대상으로 상관 계수와 검증을 목적으로한 p-value를 계산하였다.

이때 상관계수는 피어슨과 스피어만을 사용하였다.

#  상관 계수
from scipy.stats import pearsonr, spearmanr

r_age_time, p_age_time = pearsonr(df['Delivery_person_Age'], df['Time_taken(min)'])
r_rating_time, p_rating_time = pearsonr(df['Delivery_person_Ratings'], df['Time_taken(min)'])
r_deliveries_time, p_deliveries_time = pearsonr(df['multiple_deliveries'], df['Time_taken(min)'])

print(f"Age vs Time:    r={r_age_time:.3f}, p={p_age_time:.3f}")
print(f"Rating vs Time: r={r_rating_time:.3f}, p={p_rating_time:.3f}")
print(f"Deliveries vs Time: r={r_deliveries_time:.3f}, p={p_deliveries_time:.3f}")


rho_age_time, p_s_age_time = spearmanr(df['Delivery_person_Age'], df['Time_taken(min)'])
rho_rating_time, p_s_rating_time = spearmanr(df['Delivery_person_Ratings'], df['Time_taken(min)'])
rho_deliveries_time, p_s_deliveries_time = spearmanr(df['multiple_deliveries'], df['Time_taken(min)'])


print(f"Age vs Time:    r={rho_age_time:.3f}, p={p_s_age_time:.3f}")
print(f"Rating vs Time: r={rho_rating_time:.3f}, p={p_s_rating_time:.3f}")
print(f"Deliveries vs Time: r={rho_deliveries_time:.3f}, p={p_s_deliveries_time:.3f}")

 

해당 결과를 통해 배달 건수가 배달 시간과 약한 양의 상관관계를 보이는 것을 확인하였다.

따라서, 배달 건수에 따른 배달 시간 lineplot을 그렸고, 묶음 배달 수가 많을수로 배달 시간이 오래 걸린다는 결과를 얻을 수 있었다.

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

sns.lineplot(data=df,x='multiple_deliveries',y='Time_taken(min)', marker='o')
plt.title('배달 건수와 배달 시간')
plt.tight_layout()
plt.show()

 

 

그 외에도, 연령을 20대와 30대로 나뉘어 다시 데이터를 확인해보았지만, 마찬가지로 유의미한 결과를 얻지 못하였다.

 

 

5. 배달 차량 기준

차량 종류와 차량 상태에 따른 배달 시간과의 상관관계를 살펴보았다.

시각화에는 scatterplot, barplot. boxplot, violinplot을 사용하였다. 

 

 

차량 종류 기준 딱히 유의미한 결과를 확인하지 못했다.

 

차량 상태 기준으로 상태가 0인 차량이 조금 더 오랜 시간동안 배달하는 것으로 보인다.

 

따라서 차량 상태와 차량 종류 기준으로 평균 배달 시간을 구해보았다. 

 

상태가 0인 차량 종류는 motorcycle 뿐이며, 상태가 0일 때의 평균 배달 시간이 가장 높게 나타나는 것을 확인하였다.

그러나 차량 종류가 1가지이고, 해당 데이터의 배달 거리를 확인하지 않았기에 이를 추가로 확인해봐야한다.

 

 

7. 주문 날짜, 시간 기준

주문한 요일, 시간대, 주말/주중에 따른 배달 시간의 상관관계를 분석하였다. 

 

 

분석 결과, 주중/주말, 요일의 데이터 차이는 크게 확인할 수 없었고, 주로 점심시간과 저녁시간대에 배달 시간이 오래걸리는 것을 확인할 수 있었다.

 

 

또한, 주말과 주중을 시간대별로 분석해보았을 때에도 비슷한 양상을 보이는 것을 확인하였다.

 

 

추가로 요일별 시간대 분석을 해보았는데, 유독 수요일 점심시간의 배달 시간이 도드라지는 것을 확인하였다.

group_weekend_time = df.groupby(['Order_day','Hour'])['Time_taken(min)'].mean().reset_index()

plt.figure(figsize = (9,7))

sns.lineplot(data=group_weekend_time, x='Hour', y='Time_taken(min)', hue='Order_day', marker='o')

plt.title('Hour vs Avg Delivery Time by Day')
plt.xlabel('Hour of Day')
plt.ylabel('Avg Time Taken (min)')
plt.xticks(range(0, 24))  # 시간대 눈금 정렬
plt.grid(True)
plt.legend(title='Is Weekend')
plt.tight_layout()
plt.show()

 

원인을 분석하는 과정에서 3월 수요일 데이터가 해당 결과에 큰 영향을 미치는 것을 확인하였다.

2022년 3월 17-18일인 목요일과 금요일 이틀동안 인도에서 할로 축제가 진행되었는데, 해당 축제가 영향을 주었는지는 모르겠다.