- 서울시의 배달업종별 주문통화량에 대해 탐색적데이터분석을 진행한다.
- 시간별, 지역별, 배달 업종별 주문건수를 분석하여 지역선정, 업종선정, 영업 시간 등에 활용할 수 있다.
You will require Python 3 and the following libraries
- os - Used to check file list in os
- requests- Used to download the dataset.
- numpy - Used for fast matrix operations.
- pandas - Used for performing Data Analysis.
- seaborn - Used for statistical data visualization.
- matplotlib - Used to create plots and Korean character
- folium - Used for the map visualization.
- json - Used to get the json type data.
- urllib - Used for URL parsing
- bs4 - Used to get the html type data.
- warnings - Used to warning control
- 2013년 10월 ~ 2019년 9월 서울시 배달 업종별 주문건수 데이터
- 한국 공휴일 데이터
- 자치구단위 서울생활인구 일별 집계표, 서울시 주민등록인구 (구별) 통계
- 연간 주문량 변동 추이는 2013. 10. 01 ~ 2019. 09. 30 기간 데이터를 사용한다.
- 그 외 시간별 주문량과 배달 업종별 주문량 분석은 2016. 10. 01 ~ 2019. 09. 30 기간 데이터를 사용한다.
- 지역별 주문량 분석은 2018. 10. 01 ~ 2019. 09. 30 기간 데이터를 사용한다.
fig = plt.figure(figsize=[12, 10])
ax1 = fig.add_subplot(3, 2, 1)
ax1 = sns.barplot(x='year', y='count',
data=df_2013_to_2019.groupby('year')['count'].mean().reset_index())
ax2 = fig.add_subplot(3, 2, 2)
ax2 = sns.barplot(x='hour', y='count',
data=df.groupby('hour')['count'].mean().reset_index())
ax3 = fig.add_subplot(3, 2, 3)
ax3 = sns.barplot(x='month', y='count',
data=df.groupby('month')['count'].mean().reset_index())
ax4 = fig.add_subplot(3, 2, 4)
ax4 = sns.barplot(x='season', y='count',
data=df.groupby('season')['count'].mean().reset_index())
ax5 = fig.add_subplot(3, 2, 5)
ax5 = sns.barplot(x='weekday', y='count', order = ["월","화","수","목","금","토","일"],
data=df.groupby('weekday')['count'].mean().reset_index())
ax6 = fig.add_subplot(3, 2, 6)
ax6 = sns.barplot(x='holiday', y='count',
data=df.groupby('holiday')['count'].mean().reset_index())
- 연도별 주문통화량은 감소한다.
- 배달어플리케이션 이용자의 증가에 따른 감소로 예상
- 시간대별 주문량은 점심과 저녁에 몰려있고 점심보다 저녁 주문량이 많다.
- 겨울철 주문량이 다른 계절 주문량보다 많다.
- 주말 주문량이 평일 주문량보다 많다.
fig = plt.figure(figsize=(12, 10))
# 1. 시간과 휴일에 따른 count
ax1 = fig.add_subplot(2, 2, 1)
ax1 = sns.pointplot(x='hour', y='count', hue="holiday",
data=df.groupby(['holiday', 'hour'])['count'].mean().reset_index())
# 2. 시간과 요일에 따른 count
ax2 = fig.add_subplot(2, 2, 2)
ax2 = sns.pointplot(x='hour', y='count', hue="weekday", hue_order=['월', '화','수', '목','금', '토',"일"],
data=df.groupby(['weekday', 'hour'])['count'].mean().reset_index())
# 3. 시간과 계절에 따른 count
ax3 = fig.add_subplot(2, 2, 3)
ax3 = sns.pointplot(x='hour', y='count', hue="season",
data=df.groupby(['season', 'hour'])['count'].mean().reset_index())
# 4. 시간과 메뉴에 따른 count
ax4 = fig.add_subplot(2, 2, 4)
ax4 = sns.pointplot(x='hour', y='count', hue="menu",
data=df.groupby(['menu', 'hour'])['count'].mean().reset_index())
- 주말 저녁 주문을 평일 저녁 주문보다 일찍한다.
- 금요일과 토요일의 주문은 늦은시간까지 이어지는 반면, 일요일은 저녁시간대가 지나면 주문량이 급격하게 감소한다.
- 겨울, 가을의 저녁 주문을 봄, 여름의 저녁 주문보다 일찍한다.
- 점심에는 중국음식이 저녁에는 치킨이 대세 주문음식이다.
date_order.plot.line(x="일자",figsize=(20,10))
plt.grid("white")
plt.show()
date_order = date_order.set_index("일자")
monthly_order = date_order.resample('MS').mean().round(1).reset_index()
months = MonthLocator() # every month
fig, ax = plt.subplots(figsize=(20,10))
ax.plot_date(monthly_order["일자"] , \
monthly_order[["족발/보쌈","중식","치킨","피자"]], '-') # x: datetime, y: random % values
ax.xaxis.set_major_locator(months) # define xtick major location
monFmt = DateFormatter('%y년 %m월') # define xtick string format
ax.xaxis.set_major_locator(months) # apply xtick location
ax.xaxis.set_major_formatter(monFmt) # apply xtick label
plt.xticks(rotation=90)
plt.legend(monthly_order[["족발/보쌈","중식","치킨","피자"]])
plt.show()
- 치킨 주문량이 감소, 중식 주문량이 증가한 것으로 보이나, 이는 배달 어플리케이션의 등록된 치킨 업체가 중식 업체보다 많기 때문으로 판단된다.
monthly_order_2 = date_order.resample('M').sum().reset_index()
monthly_order_2["일자"] = monthly_order_2["일자"].dt.month
monthly_order_2 = monthly_order_2.groupby("일자").mean().round(1)
monthly_order_2.plot.line(figsize=(20,10))
plt.xticks([1,2,3,4,5,6,7,8,9,10,11,12])
plt.xlabel(None)
plt.show()
- 배달업종에 따른 주문량의 scale차이가 크게 나므로 정규화 진행
col = ["족발/보쌈", "중식", "치킨", "피자"]
monthly_order_2_norm = ((monthly_order_2[col]-monthly_order_2[col].min()) / (monthly_order_2[col].max()-monthly_order_2[col].min())).round(3)
monthly_order_2_norm.plot.line(figsize=(20,10))
plt.xlabel(None)
plt.xticks([1,2,3,4,5,6,7,8,9,10,11,12])
plt.show()
- 치킨은 3월과 12월에 주문량이 두드러진다.
- 중식과 족발/보쌈은 7월과 8월에 주문량이 두드러진다.
- 피자는 12월에 주문량이 두드러진다.
date_order.boxplot(figsize=(12,8))
- 치킨과 중식의 배달량이 가장많고
- 치킨, 족발/보쌈, 피자의 outlier는 upper fence 상단에,
- 중식의 outlier는 lower fence 하단에 분포
여기에는 각 outlier 나오게된 그 파일 넣으면 좋을듯
day_order = data.pivot_table("통화건수", "요일", "업종").round(1)
day_order_sort = pd.DataFrame(columns=["요일", "족발/보쌈", "중식", "치킨", "피자"])
day_order_sort.loc[0] = day_order.loc["월"]
day_order_sort.loc[1] = day_order.loc["화"]
day_order_sort.loc[2] = day_order.loc["수"]
day_order_sort.loc[3] = day_order.loc["목"]
day_order_sort.loc[4] = day_order.loc["금"]
day_order_sort.loc[5] = day_order.loc["토"]
day_order_sort.loc[6] = day_order.loc["일"]
day_order_sort["요일"] = ["월", "화", "수", "목", "금", "토", "일"]
day_order_sort.set_index("요일")
# 정규화
day_order_norm = pd.concat([day_order_sort["요일"], \
(day_order_sort[col]-day_order_sort[col].min()) / (day_order_sort[col].max()-day_order_sort[col].min())], axis=1)
day_order_norm
day_order_norm.plot.line(x="요일", figsize=(20,10))
- 치킨과 족발/보쌈은 토요일에 주문량이 가장 많고
- 피자와 중식을 일요일에 주문량이 가장 많다
df_sigu = datas.groupby(['시군구']).sum()
df_sigu = df_sigu.drop(['일자','시간대'],axis=1).reset_index()
df_sigu= df_sigu.sort_values('통화건수',ascending =False)
df_sigu.head()
- 주문건수 높은 5개구
시군구 | 통화건수 |
---|---|
강남구 | 1047814 |
강서구 | 1014216 |
중구 | 752301 |
서초구 | 730401 |
서대문구 | 668737 |
geo_path = './03_skorea_municipalities_geo_simple.json'
geo_str = json.load(open(geo_path, encoding='utf-8'))
df_map = folium.Map(location=[37.5502,126.982], zoom_start = 11,\
tiles= 'cartodbpositron')
# folium
folium.Choropleth(
geo_data = geo_str,
data = df_sigu, columns = ['시군구','통화건수'],
nan_fill_color = 'purple', nan_fill_opacity =0.3,
key_on = 'feature.id',fill_color= 'Blues',
legend_name = '2019년 구별 주문건수 합계'
).add_to(df_map)
# 주문건수별 바 그래프
plt.figure(figsize=(12,6))
sns.barplot(x = '통화건수', y='시군구',data =df_sigu[:6],palette ='Blues_d' )
df_ppl = pd.read_csv("./0. raw_datas/ppl_report.txt",sep='\t',encoding='utf-8',thousands = ',')
df_ppl = df_ppl[3:]
df_ppl['인구'] = df_ppl['인구'].str.replace(',','').astype('int')
ppl_sigu = df_ppl[['자치구','인구']]
ppl_sigu = ppl_sigu.rename({'자치구':'시군구'},axis= 1)
ppl_sigu = ppl_sigu.sort_values('인구',ascending =False)
geo_path = './03_skorea_municipalities_geo_simple.json'
geo_str = json.load(open(geo_path, encoding='utf-8'))
# folium
df_map = folium.Map(location=[37.5502,126.982], zoom_start = 11,\
tiles= 'cartodbpositron')
folium.Choropleth(
geo_data = geo_str,
data = ppl_sigu, columns = ['시군구','인구'],
nan_fill_color = 'purple', nan_fill_opacity =0.3,
key_on = 'feature.id',fill_color= 'Blues',
legend_name = '2019년 서울시 구별 인구수'
).add_to(df_map)
# 인구별 바 그래프
plt.figure(figsize=(12,6))
sns.barplot(x = '인구', y='시군구',data =ppl_sigu[:6],palette ='Blues_d' )
df['주문율'] = df['통화건수'] / df['인구']
df.sort_values('주문율',ascending= False,inplace= True)
# folium
df_map = folium.Map(location=[37.5502,126.982], zoom_start = 11,\
tiles= 'cartodbpositron')
folium.Choropleth(
geo_data = geo_str,
data = df, columns = ['시군구','주문율'],
nan_fill_color = 'purple', nan_fill_opacity =0.3,
key_on = 'feature.id',fill_color= 'Blues',
legend_name = '2019년 서울시 구별 거주인구 대비 통화량(주문율)'
).add_to(df_map)
# 주문율 바 그래프
plt.figure(figsize=(10,3))
sns.barplot(x = '주문율', y='시군구',data =df[:5],palette ='Blues_d' )