python项目实战:酒店需求分析(hotel demand booking)
酒店预定需求分析报告
数据来源:https://www.kaggle.com/jessemostipak/hotel-booking-demand
包含了城市酒店与度假酒店的预定信息
目录
字段说明
数据处理
酒店自身运营情况
总营业额
按年
按月
人均每晚房价比较
月份
房间类型
市场细分
入住率与取消率比较
客户行为分析
国籍
入住时间(按月)
提前预定时长(按月)
入住时长
餐型选择
预定渠道
1.字段说明
- hotel:酒店(H1=度假酒店或H2=城市酒店)
- is_canceled:值,表明预订是否取消(1)或不取消(0)
- lead_time:输入预订日期至抵达日期之间的天数
- arrival_date_year:抵达日期
- arrival_date_month:抵达日期月份
- arrival_date_week_number:到达日期的年份周数
- arrival_date_day_of_month:抵达日期
- stays_in_weekend_nights:周末(星期六或星期天)客人入住或预定入住酒店的次数
- stays_in_week_nights:每周晚上(星期一至星期五)客人入住或预定入住酒店的次数
- adults:成人人数
- children:儿童人数
- babies:婴儿数量
- meal:预订的餐型。 类别以标准招待餐包提供:
- 未定义/SC-无餐包;
- BB-早餐;
- HB-早餐和其他一顿饭-通常是晚餐);
- FB-早餐、午餐和晚餐)
- country:原籍国。 类别以ISO3155-3:2013格式表示
- market_segment:市场细分名称。
- distribution_channel:预订分销渠道。 「TA」一词指「旅行社」,「TO」指「旅游经营者」
- is_repeated_guest:值,指示预订名称是否来自重复的客人(1)或不(0)
- previous_cancellations:客户在当前预订前取消的先前预订数
- previous_bookings_not_canceled:客户在本次预订前未取消的先前预订数
- reserved_room_type:房间类型的代码保留。 代码是以匿名为由而不是指定的。
- assigned_room_type:指定预订的房间类型代码。 有时,由于酒店经营的原因,指定的房间类型与预订的房间类型不同(例如。 超额预订)或客户要求。 代码是以匿名为由而不是指定的。
- booking_changes:从预订在PMS系统中输入之日起至入住或取消之日止,对预订所作的更改/修改的数目
- deposit_type:说明客户是否存款以保证预订。 这个变量可以假设三类:
- Non Deposit-无预付保证金;
- Non Refund-房价全额提前预付,取消不退款;
- Refundable-部分房价预付,取消可退款。
- agent:预订的旅行社的身份证
- company:进行预订的公司/实体的ID或负责支付预订。 以身份证明而不是匿名为由指定
- days_in_waiting_list:在客户确认预订前,预订在等待名单中的天数
- customer_type:预订类型,假设四类之一:
- 合同-当预订有分配或与之相关的其他类型的合同时;
- 集团-当预订与一个集团相关联时;
- 短暂-当预订不是一个集团或合同的一部分,并且与其他短暂预订无关时;
- 短暂-当预订是短暂的,但至少与其他短暂预订有关时
- ADR:每日平均收费,除以所有住宿交易之和以住宿夜总数
- required_car_parking_spaces:客户要求的汽车停车位数量
- total_of_special_requests:客户提出的特殊要求的数量(例如。 双人床或高层)
- reservation_status:保留最后状态,假设三类之一:
- 取消-预订被客户取消;
- 退房-客户已入住,但已离开;
- 不-展示-客户没有入住,并确实通知酒店为什么
- reservation_status_date:设置最后状态的日期。 此变量可与预订状态一起使用,以了解预订何时取消或客户何时退房。
2.数据处理
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.express as px
#可视化显示在页面
%matplotlib inline
#中文字体
plt.rcParams['font.sans-serif']=['SimHei']
#负数正常显示
plt.rcParams['axes.unicode_minus']=False
#忽略警告
import warnings
warnings.filterwarnings('ignore')
#导入数据
df=pd.read_csv('hotel_booking_demand.csv',encoding='gbk')
df.head()
hotel is_canceled lead_time arrival_date_year arrival_date_month arrival_date_week_number arrival_date_day_of_month stays_in_weekend_nights stays_in_week_nights adults ... deposit_type agent company days_in_waiting_list customer_type adr required_car_parking_spaces total_of_special_requests reservation_status reservation_status_date
0 Resort Hotel 0 342 2015 July 27 1 0 0 2 ... No Deposit NaN NaN 0 Transient 0.0 0 0 Check-Out 2015-07-01
1 Resort Hotel 0 737 2015 July 27 1 0 0 2 ... No Deposit NaN NaN 0 Transient 0.0 0 0 Check-Out 2015-07-01
2 Resort Hotel 0 7 2015 July 27 1 0 1 1 ... No Deposit NaN NaN 0 Transient 75.0 0 0 Check-Out 2015-07-02
3 Resort Hotel 0 13 2015 July 27 1 0 1 1 ... No Deposit 304.0 NaN 0 Transient 75.0 0 0 Check-Out 2015-07-02
4 Resort Hotel 0 14 2015 July 27 1 0 2 2 ... No Deposit 240.0 NaN 0 Transient 98.0 0 1 Check-Out 2015-07-03
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 119390 entries, 0 to 119389
Data columns (total 32 columns):# Column Non-Null Count Dtype
--- ------ -------------- ----- 0 hotel 119390 non-null object 1 is_canceled 119390 non-null int64 2 lead_time 119390 non-null int64 3 arrival_date_year 119390 non-null int64 4 arrival_date_month 119390 non-null object 5 arrival_date_week_number 119390 non-null int64 6 arrival_date_day_of_month 119390 non-null int64 7 stays_in_weekend_nights 119390 non-null int64 8 stays_in_week_nights 119390 non-null int64 9 adults 119390 non-null int64 10 children 119386 non-null float6411 babies 119390 non-null int64 12 meal 119390 non-null object 13 country 118902 non-null object 14 market_segment 119390 non-null object 15 distribution_channel 119390 non-null object 16 is_repeated_guest 119390 non-null int64 17 previous_cancellations 119390 non-null int64 18 previous_bookings_not_canceled 119390 non-null int64 19 reserved_room_type 119390 non-null object 20 assigned_room_type 119390 non-null object 21 booking_changes 119390 non-null int64 22 deposit_type 119390 non-null object 23 agent 103050 non-null float6424 company 6797 non-null float6425 days_in_waiting_list 119390 non-null int64 26 customer_type 119390 non-null object 27 adr 119390 non-null float6428 required_car_parking_spaces 119390 non-null int64 29 total_of_special_requests 119390 non-null int64 30 reservation_status 119390 non-null object 31 reservation_status_date 119390 non-null object
dtypes: float64(4), int64(16), object(12)
memory usage: 29.1+ MB
总共有119389条数据,32个观测指标,存在缺失数据。
###查找缺失数据
df.isnull().sum()[df.isnull().sum()!=0]
children 4
country 488
agent 16340
company 112593
dtype: int64
发现children,country,agent,company中存在缺失数据。
其中children很可能是因为没有儿童入住,所以可以用0填补缺失值;
country则可以用众数取代;
而agent和company缺失值过多,可以删除该观测指标。
#缺失值处理
df['children']=df['children'].fillna(0)
df['country']=df['country'].fillna(value=df.country.mode()[0])
df.drop(['agent'],axis=1,inplace=True)
df.drop(['company'],axis=1,inplace=True)
#检查
df.isnull().sum()[df.isnull().sum()!=0]
Series([], dtype: int64)
#更改数据类型(更改reservation_status_date为日期型)
df['reservation_status_date']=df['reservation_status_date'].astype('datetime64[ns]')
#添加一列为抵达日期'arrival_date',并令其数据类型为日期型
df['arrival_date']=df['arrival_date_year'].map(str)+'/'+df['arrival_date_month'].map(str)+'/'+df['arrival_date_day_of_month'].map(str)
df['arrival_date']=df['arrival_date'].astype('datetime64[ns]')
#查看修改后的数据类型
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 119390 entries, 0 to 119389
Data columns (total 31 columns):# Column Non-Null Count Dtype
--- ------ -------------- ----- 0 hotel 119390 non-null object 1 is_canceled 119390 non-null int64 2 lead_time 119390 non-null int64 3 arrival_date_year 119390 non-null int64 4 arrival_date_month 119390 non-null object 5 arrival_date_week_number 119390 non-null int64 6 arrival_date_day_of_month 119390 non-null int64 7 stays_in_weekend_nights 119390 non-null int64 8 stays_in_week_nights 119390 non-null int64 9 adults 119390 non-null int64 10 children 119390 non-null float64 11 babies 119390 non-null int64 12 meal 119390 non-null object 13 country 119390 non-null object 14 market_segment 119390 non-null object 15 distribution_channel 119390 non-null object 16 is_repeated_guest 119390 non-null int64 17 previous_cancellations 119390 non-null int64 18 previous_bookings_not_canceled 119390 non-null int64 19 reserved_room_type 119390 non-null object 20 assigned_room_type 119390 non-null object 21 booking_changes 119390 non-null int64 22 deposit_type 119390 non-null object 23 days_in_waiting_list 119390 non-null int64 24 customer_type 119390 non-null object 25 adr 119390 non-null float64 26 required_car_parking_spaces 119390 non-null int64 27 total_of_special_requests 119390 non-null int64 28 reservation_status 119390 non-null object 29 reservation_status_date 119390 non-null datetime64[ns]30 arrival_date 119390 non-null datetime64[ns]
dtypes: datetime64[ns](2), float64(2), int64(16), object(11)
memory usage: 28.2+ MB
3.酒店自身运营情况
#不同年份两家酒店总营业额比较
df['total_adr']=(df['stays_in_weekend_nights']+df['stays_in_week_nights'])*df['adr']
df.pivot_table(values='total_adr',index='arrival_date_year',columns='hotel',aggfunc='sum').plot.bar()
plt.show()
发现除2015年,城市酒店的年总销售额均比度假酒店高。
#将月份英文转换成数值
df['arrival_date_month']=df['arrival_date_month'].map({'July':7,'August':8,'September':9,'October':10,'November':11,'December':12,'January':1,'February':2,'March':3,'April':4,'May':5,'June':6,})
#不同月份两家酒店营业额比较
df.pivot_table(values='total_adr',index='arrival_date_month',columns='hotel',aggfunc='sum').plot.bar()
plt.show()
发现,7,8月份度假酒店的月营业额高于城市酒店,其余月份的销售额均是城市酒店高于度假酒店,且两家酒店月营业额走势一致。
#按月份两家酒店日均收费比较
df.pivot_table(values='adr',index='arrival_date_month',columns='hotel',aggfunc='mean').plot()
可以看出,度假酒店按月的日均收费变化较大,七八月份的日均收费较高,这可能是其此时月营业额高于城市酒店的原因;
大多数时候城市酒店的日均收费高于度假酒店。
#两家酒店各类型房间日均收费比较
sns.factorplot(x='reserved_room_type',y='adr',hue='hotel',data=df.query('adr<1000'),size=6,kind='box',aspect=1)
plt.title("不同类型房间日均收费", fontsize=20)
plt.xlabel("房间类型", fontsize=16)
plt.ylabel("日均收费", fontsize=16)
plt.show()
度假酒店普遍低价位且房间类型较多,价位普遍在100左右,受极小值影响;
城市酒房型消费较度假酒店高,中位数处于中间水平,极值影响小。
#不同市场细分下房间日均收费的比较
sns.factorplot(x='market_segment',y='adr',hue='hotel',data=df.query('adr<400'),size=6,kind='box',aspect=1)
plt.title("不同市场细分下人均每晚价格", fontsize=20)
plt.xlabel("市场细分", fontsize=16)
plt.ylabel("人均每晚价格", fontsize=16)
plt.show()
从箱线图可以看出两家酒店大多是从线上预定或者直接现场预订,与其价格相对合理有关,而航空公司的价格高,通过该市场预订的也就少。
#两家酒店预定是否取消
a=df[df['is_canceled']==0].groupby('hotel').is_canceled.count()
b=df[df['is_canceled']==1].groupby('hotel').is_canceled.count()
data=pd.DataFrame({'hotel':a.index,'0':a.values,'1':b.values})
data['未取消比']=data['0']/(data['0']+data['1'])
data['取消比']=data['1']/(data['0']+data['1'])
data
hotel 0 1 未取消比 取消比
0 City Hotel 46228 33102 0.582730 0.417270
1 Resort Hotel 28938 11122 0.722366 0.277634
相对而言,整体上城市酒店的取消率高于度假酒店。
#当前预订前取消的先前预订对预订取消率的影响
plt.figure(figsize=(10,6))
df1=df.groupby('previous_cancellations')['is_canceled'].describe()
sns.regplot(x=df1.index,y=df1['mean']*100,data=df1,color='g')
plt.title('当前预订前取消的先前预订对预订取消率的影响',fontsize=20)
plt.xlabel('当前预订前取消的先前预订数',fontsize=16)
plt.ylabel('取消率(%)',fontsize=16)
plt.show()
可以发现当前预定前取消的先前预定数越多,预订取消率越高。
#提前预订时长对取消的影响
plt.figure(figsize=(10,6))
df2=df.groupby('lead_time')['is_canceled'].describe()
sns.regplot(x=df2.index,y=df2['mean']*100,data=df2,color='g')
plt.title('提前预定时长对取消的影响',fontsize=20)
plt.xlabel('提前预定时长',fontsize=16)
plt.ylabel('取消率(%)',fontsize=16)
plt.show()
从散点图可以发现,取消率与提前预订时长有一定的关系,提前预定时长越长,取消率越高。
#不同付款方式对取消率的影响
df3=df.groupby('deposit_type')['is_canceled'].describe()
plt.figure(figsize=(8,6))
sns.barplot(x=df3.index,y=df3['mean']*100,data=df3)
plt.title("不同付款方式对取消率的影响", fontsize=20)
plt.xlabel("付款方式", fontsize=16)
plt.ylabel("取消率(%)", fontsize=16)
plt.show()
可以发现,Non Refund付款方式的取消率最高。
#不同预定渠道对取消率的影响
df4=df.groupby('distribution_channel')['is_canceled'].describe()
plt.figure(figsize=(8,6))
sns.barplot(x=df4.index,y=df4['mean']*100,data=df4)
plt.title("不同预定渠道对取消率的影响", fontsize=20)
plt.xlabel("预定渠道", fontsize=16)
plt.ylabel("取消率(%)", fontsize=16)
plt.show()
在Undefined渠道下预订,客户的取消率较高。
4.客户行为分析
#客户国籍分布
df5=pd.DataFrame({'客户总数':df['country'].value_counts()})
px.choropleth(df5,locations=df5.index,color='客户总数',hover_name='客户总数',color_continuous_scale=px.colors.sequential.Plasma,title="客户分布").show()
客户主要集中在欧洲地区。
#入住时间(按月)
plt.figure(figsize=(16,5))
plt.subplot(1,2,1)
df.query("hotel=='City Hotel'").arrival_date_month.value_counts().sort_index().plot.bar()
plt.title("城市酒店入住时间(按月)", fontsize=20)
plt.xlabel("月份", fontsize=16)
plt.ylabel("频率", fontsize=16)
plt.subplot(1,2,2)
df.query("hotel=='Resort Hotel'").arrival_date_month.value_counts().sort_index().plot.bar()
plt.title("度假酒店入住时间(按月)", fontsize=20)
plt.xlabel("月份", fontsize=16)
plt.ylabel("频率", fontsize=16)
plt.show()
城市酒店4-10月酒店入住的频率变化不大,1、2、11、12月为入住淡季;
度假酒店7、8月份为入住旺季,很可能与此时为旅游旺季有关。
#按月提前预定时长
sns.factorplot(x='arrival_date_month',y='lead_time',hue='hotel',data=df,size=6)
plt.title("提前预定时长(按月)", fontsize=20)
plt.xlabel("月份", fontsize=16)
plt.ylabel("预定时长", fontsize=16)
plt.show()
(客户抵达酒店)城市酒店的7、8月份,度假酒店的5、6、9月份客户提前预定的时长较长。
#入住时长
df['total_stay']=df['stays_in_weekend_nights']+df['stays_in_week_nights']
plt.figure(figsize=(12,5))
plt.subplot(1,2,1)
df.query("total_stay<30&hotel=='City Hotel'").total_stay.plot.hist(bins=15,color='r')
plt.title("城市酒店入住时长", fontsize=20)
plt.xlabel("天数(区间)", fontsize=16)
plt.ylabel("频率", fontsize=16)
plt.subplot(1,2,2)
df.query("total_stay<30&hotel=='Resort Hotel'").total_stay.plot.hist(bins=15)
plt.title("度假酒店入住时长", fontsize=18)
plt.xlabel("天数(区间)", fontsize=16)
plt.ylabel("频率", fontsize=16)
plt.show()
城市酒店入住时长绝大多数在五天以内;
度假酒店入住时长绝大多是在七天以内。
#餐型选择
plt.figure(figsize=(12,6))
plt.subplot(1,2,1)
plt.pie(df.query("hotel=='City Hotel'").meal.value_counts(),labels=df.query("hotel=='City Hotel'").meal.value_counts().index,autopct='%.2f%%')
plt.title("城市酒店不同餐型选择占比(%)", fontsize=20)
plt.legend()
plt.subplot(1,2,2)
plt.pie(df.query("hotel=='Resort Hotel'").meal.value_counts(),labels=df.query("hotel=='Resort Hotel'").meal.value_counts().index,autopct='%.2f%%')
plt.title("度假酒店不同餐型选择占比(%)", fontsize=20)
plt.legend()
plt.show()
城市酒店与度假酒店餐型选择大体一致,大多数选择仅早餐(BB)。
#预定渠道
plt.figure(figsize=(12,6))
plt.subplot(1,2,1)
plt.pie(df.query("hotel=='City Hotel'").distribution_channel.value_counts(),labels=df.query("hotel=='City Hotel'").distribution_channel.value_counts().index,autopct='%.2f%%')
plt.title("城市酒店预订渠道选择占比(%)", fontsize=20)
plt.legend()
plt.subplot(1,2,2)
plt.pie(df.query("hotel=='Resort Hotel'").distribution_channel.value_counts(),labels=df.query("hotel=='Resort Hotel'").distribution_channel.value_counts().index,autopct='%.2f%%')
plt.title("度假酒店预定渠道选择占比(%)", fontsize=20)
plt.legend()
plt.show()
城市酒店与度假酒店预订渠道的选择大体一致,通过旅行社和旅游经营者预订的占绝大多数。
python项目实战:酒店需求分析(hotel demand booking)相关推荐
- Python项目实战:开发PetStore宠物商店项目-关东升-专题视频课程
Python项目实战:开发PetStore宠物商店项目-487人已学习 课程介绍 课程内容包括项目分析与设计过程.数据库设计过程.项目敏捷开发.MySQL数据库.Python访问数据库 ...
- Python项目实战 —— 04. 淘宝用户行为分析
Python项目实战 Python项目实战--目录 Python项目实战 -- 04. 淘宝用户行为分析 一.背景 二.解题思路 三.数据分析 3.1 数据清洗 3.2 数据分析 3.2.1 用户整体 ...
- Python项目实战:数据可视化与股票数据分析-关东升-专题视频课程
Python项目实战:数据可视化与股票数据分析-333人已学习 课程介绍 本视频内容包括使用Matplotlib绘制图表.MySQL数据库.Python访问数据库和Lambda表达式. ...
- Python项目实战:使用PySpark对大数据进行分析
Python项目实战:使用PySpark对大数据进行分析 大数据,顾名思义就是大量的数据,一般这些数据都是PB级以上.PB是数据存储容量的单位,它等于2的50次方个字节,或者在数值上大约等于1000个 ...
- python项目实战——银行取款机系统(七)
项目实战目录 python项目实战--银行取款机系统(一) python项目实战--银行取款机系统(二) python项目实战--银行取款机系统(三) python项目实战--银行取款机系统(四) p ...
- python项目实战——银行取款机系统(一)
项目实战目录 python项目实战--银行取款机系统(一) 前言 今天我们将通过python完成简易银行提款机系统的实战,我们一步步实现我们的要求.话不多说,看操作. 环境使用 python 3.9 ...
- python项目实战——银行取款机系统(六)
项目实战目录 python项目实战--银行取款机系统(一) python项目实战--银行取款机系统(二) python项目实战--银行取款机系统(三) python项目实战--银行取款机系统(四) p ...
- Python项目实战 —— 02. 疫情前后全国人口流动可视化大屏
Python项目实战 Python项目实战--目录 Python项目实战 -- 02. 疫情前后全国人口流动可视化大屏 一.背景 二.数据分析 2.1 数据处理 2.2 画图 2.3 展示 三.可视化 ...
- python项目实战——银行取款机系统(二)
项目实战目录 python项目实战--银行取款机系统(一) python项目实战--银行取款机系统(二) 前言 环境使用 python 3.9 pycharm 模块使用 requests random ...
- Python项目实战 —— 01. 疾病预测结构化数据
Python项目实战 Python项目实战--目录 Python项目实战 -- 01. 疾病预测结构化数据 一.背景 二.解题思路 三.数据分析 3.1 数据清洗 3.2 数据分析 3.2.1 相关系 ...
最新文章
- mysql触发器删除同步_MySQL 触发器例子(两张表同步增加和删除)
- linux proc 占用空间,一种诡异的Linux磁盘空间被占满问题
- 【数字信号处理】基于DFT的滤波系列3之插值滤波(含MATLAB代码)
- group by 和where 条件后面不能用刚设置的别名。
- python做定时任务api_Python—定时任务(APScheduler实现)
- 【原创】IDEA一定要改的八条配置
- “编程能力差,90%会输在这点上!”谷歌开发:方法不对,努力也白费
- MySQL数据库面试题(2022年最新版45题)
- java mybatisplus Error parsing time stamp
- excel冻结窗口怎么设置_说说Word和Excel表头共享,全部方法供你选择
- wps连接mysql odbc_如何在WPS中使用ADO连接数据库?
- lisp语言如何画小红点_用AutoLISP语言编程实现参数化绘图
- 接口测试 - 从0不到1的心路历程 (二)
- 切片器可以设置日期格式?_Excel切片器,原来有这么多厉害的用法
- 论文阅读:Convolutional Neural Networks for Sentence Classification 卷积神经网络的句子分类
- mysql5.7.2.6以上版本没有my.cnf解决办法
- STM32 NEC红外遥控器解码
- Shamir 门限秘密共享
- 操作系统真象还原[11章]-用户进程
- MeshLab使用经验
热门文章
- mac linux makefile,Makefile简单入门
- 如何将Notepad++设置到鼠标右键(注册表)里去
- 【安全管理】甲方企业漏洞管理活动的50个痛点总结
- 对乌云网事件的一点点浅薄思考
- IDE /skipping incompatible xxx_d.dll when searching for -lxxx_d
- 云原生Docker镜像管理
- 数据过大时dataloader怎么设计?
- CPU | Cache 基本概念和基本原理
- 不断学习和提高写作水平,使公文写作更加得心应手和高效精准
- Guava入门~CacheStats