酒店预定需求分析报告

数据来源: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)相关推荐

  1. Python项目实战:开发PetStore宠物商店项目-关东升-专题视频课程

    Python项目实战:开发PetStore宠物商店项目-487人已学习 课程介绍         课程内容包括项目分析与设计过程.数据库设计过程.项目敏捷开发.MySQL数据库.Python访问数据库 ...

  2. Python项目实战 —— 04. 淘宝用户行为分析

    Python项目实战 Python项目实战--目录 Python项目实战 -- 04. 淘宝用户行为分析 一.背景 二.解题思路 三.数据分析 3.1 数据清洗 3.2 数据分析 3.2.1 用户整体 ...

  3. Python项目实战:数据可视化与股票数据分析-关东升-专题视频课程

    Python项目实战:数据可视化与股票数据分析-333人已学习 课程介绍         本视频内容包括使用Matplotlib绘制图表.MySQL数据库.Python访问数据库和Lambda表达式. ...

  4. Python项目实战:使用PySpark对大数据进行分析

    Python项目实战:使用PySpark对大数据进行分析 大数据,顾名思义就是大量的数据,一般这些数据都是PB级以上.PB是数据存储容量的单位,它等于2的50次方个字节,或者在数值上大约等于1000个 ...

  5. python项目实战——银行取款机系统(七)

    项目实战目录 python项目实战--银行取款机系统(一) python项目实战--银行取款机系统(二) python项目实战--银行取款机系统(三) python项目实战--银行取款机系统(四) p ...

  6. python项目实战——银行取款机系统(一)

    项目实战目录 python项目实战--银行取款机系统(一) 前言 今天我们将通过python完成简易银行提款机系统的实战,我们一步步实现我们的要求.话不多说,看操作. 环境使用 python 3.9 ...

  7. python项目实战——银行取款机系统(六)

    项目实战目录 python项目实战--银行取款机系统(一) python项目实战--银行取款机系统(二) python项目实战--银行取款机系统(三) python项目实战--银行取款机系统(四) p ...

  8. Python项目实战 —— 02. 疫情前后全国人口流动可视化大屏

    Python项目实战 Python项目实战--目录 Python项目实战 -- 02. 疫情前后全国人口流动可视化大屏 一.背景 二.数据分析 2.1 数据处理 2.2 画图 2.3 展示 三.可视化 ...

  9. python项目实战——银行取款机系统(二)

    项目实战目录 python项目实战--银行取款机系统(一) python项目实战--银行取款机系统(二) 前言 环境使用 python 3.9 pycharm 模块使用 requests random ...

  10. Python项目实战 —— 01. 疾病预测结构化数据

    Python项目实战 Python项目实战--目录 Python项目实战 -- 01. 疾病预测结构化数据 一.背景 二.解题思路 三.数据分析 3.1 数据清洗 3.2 数据分析 3.2.1 相关系 ...

最新文章

  1. mysql触发器删除同步_MySQL 触发器例子(两张表同步增加和删除)
  2. linux proc 占用空间,一种诡异的Linux磁盘空间被占满问题
  3. 【数字信号处理】基于DFT的滤波系列3之插值滤波(含MATLAB代码)
  4. group by 和where 条件后面不能用刚设置的别名。
  5. python做定时任务api_Python—定时任务(APScheduler实现)
  6. 【原创】IDEA一定要改的八条配置
  7. “编程能力差,90%会输在这点上!”谷歌开发:方法不对,努力也白费
  8. MySQL数据库面试题(2022年最新版45题)
  9. java mybatisplus Error parsing time stamp
  10. excel冻结窗口怎么设置_说说Word和Excel表头共享,全部方法供你选择
  11. wps连接mysql odbc_如何在WPS中使用ADO连接数据库?
  12. lisp语言如何画小红点_用AutoLISP语言编程实现参数化绘图
  13. 接口测试 - 从0不到1的心路历程 (二)
  14. 切片器可以设置日期格式?_Excel切片器,原来有这么多厉害的用法
  15. 论文阅读:Convolutional Neural Networks for Sentence Classification 卷积神经网络的句子分类
  16. mysql5.7.2.6以上版本没有my.cnf解决办法
  17. STM32 NEC红外遥控器解码
  18. Shamir 门限秘密共享
  19. 操作系统真象还原[11章]-用户进程
  20. MeshLab使用经验

热门文章

  1. mac linux makefile,Makefile简单入门
  2. 如何将Notepad++设置到鼠标右键(注册表)里去
  3. 【安全管理】甲方企业漏洞管理活动的50个痛点总结
  4. 对乌云网事件的一点点浅薄思考
  5. IDE /skipping incompatible xxx_d.dll when searching for -lxxx_d
  6. 云原生Docker镜像管理
  7. 数据过大时dataloader怎么设计?
  8. CPU | Cache 基本概念和基本原理
  9. 不断学习和提高写作水平,使公文写作更加得心应手和高效精准
  10. Guava入门~CacheStats