【数据分析实战】基于python对酒店预订需求进行分析

news2024/10/5 21:15:16

请添加图片描述

文章目录

  • 📚引言
  • 📖数据加载以及基本观察
    • 📑缺失值观察及处理
      • 🔖缺失值观察以及可视化
      • 🔖缺失值处理
  • 📖用户数据探索
    • 📑什么时间预定酒店将会更经济实惠?
    • 📑哪个月份的酒店预订是最繁忙的?
  • 📖商家数据探索
    • 📑按市场细分的不同预定情况是怎样的?
    • 📑什么样的人更容易取消预订?
      • 🔖数据编码
      • 🔖特征筛选
      • 🔖构建模型并预测
      • 🔖根据特征重要性得出结论
  • 📍总结

📚引言

🙋‍♂️作者简介:生鱼同学,大数据科学与技术专业硕士在读👨‍🎓,曾获得华为杯数学建模国家二等奖🏆,MathorCup 数学建模竞赛国家二等奖🏅,亚太数学建模国家二等奖🏅。

✍️研究方向:复杂网络科学

🏆兴趣方向:利用python进行数据分析与机器学习,数学建模竞赛经验交流,网络爬虫等。

在有预定酒店的需求时,你是否考虑过以下的问题:

  • 你是否曾想过每年什么时候是预订酒店房间的最佳时间?
  • 为了获得最佳的每日价格,最佳的逗留时间?
  • 如果你想预测一家酒店是否有可能收到过多的特殊要求呢?

在本文中我们就对Kaggle平台上的酒店需求数据集进行分析,这个数据集包含了一家城市酒店和一家度假酒店的预订信息,并包括诸如预订时间、逗留时间、成人、儿童和/或婴儿的数量,以及可用的停车位数量等信息。话不多说,我们开始吧。

本项目中的数据来源于Kaggle开放数据Hotel booking demand链接如下:
Hotel booking demand
需要的小伙伴可以自行下载获取。

📖数据加载以及基本观察

在进行数据加载之前,我们首先对数据的各个列进行解释,具体情况如下表所示:

列名表达含义
hotel酒店(H1=度假酒店或H2=城市酒店)
is_canceled表示预订是否被取消(1)或不被取消(0)的值。
lead_time从预订进入PMS的日期到抵达日期之间的天数。
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国家。类别以ISO 3155-3:2013的格式表示
market_segment市场细分的指定。在类别中,"TA "指 “旅行社”,"TO "指 “旅游经营者”。
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指明客户是否支付了押金以保证预订。这个变量可以有三个类别: 无押金–没有押金;不退款–押金的价值相当于总住宿费用;可退款–押金的价值低于总住宿费用。
agent进行预订的旅行社的ID
company进行预订或负责支付预订的公司/实体的ID。出于匿名的原因,将出示身份证而不是指定的身份。
days_in_waiting_list预订在确认给客户之前在等待名单中的天数
customer_type预订的类型,假设是四类之一: 合同–当预订有一个分配或其他类型的合同与之相关时;团体–当预订与一个团体相关时;暂住–当预订不是团体或合同的一部分,并且没有与其他暂住预订相关时;暂住方–当预订是暂住的,但至少与其他暂住预订相关时
adr日均房价的定义是用所有住宿交易的总和除以总的住宿夜数。
required_car_parking_spaces预客户需要的车位数量
total_of_special_requests客户提出的特殊要求的数量(如双床或高楼层)。
reservation_status预订的最后状态,假设是三类中的一类: 取消–预订被客户取消;退房–客户已入住但已离开;未入住–客户未入住但已通知酒店原因
reservation_status_date最后一次设置状态的日期。这个变量可以和ReservationStatus一起使用,以了解预订何时被取消或客户何时退房。

可以看到,数据所给出的特征还是比较多的。接下来我们就基于上述数据来解决一些商业角度可能关心的问题,本文解决的问题如下:

首先是从用户的角度来看关心的问题:

  • 什么时间预定酒店将会更经济实惠?
  • 哪个月份的酒店预订是最繁忙的?

其次是商家更容易关心的问题:

  • 客人来自哪里?
  • 按市场细分的不同预定情况是怎样的?
  • 对酒店提出特殊要求的人有什么共同点?
  • 什么样的人更容易取消预订?

首先我们调用**info()**函数来对数据进行初步的观察。代码和结果如下:
在这里插入图片描述
我们可以看到,公司这列有明显的缺失情况。与此同时,在这里我们也能了解到不同的数据类型。

📑缺失值观察及处理

🔖缺失值观察以及可视化

首先提取所有缺失的列以及它们缺失的个数情况,代码如下:

data_missing = data.isnull().sum()
data_missing = data_missing[data_missing > 0]
data_missing

结果如下:
在这里插入图片描述
接下来,我们对数据的缺失值进行一些简单的柱状图可视化。代码如下:

data_missing.plot.bar()

在这里插入图片描述

🔖缺失值处理

我们首先来看一下缺失值的实际意义代表情况,如下:

列名表达含义
children小孩的个数
country国家。类别以ISO 3155-3:2013的格式表示
agent进行预订的旅行社的ID
company进行预订或负责支付预订的公司/实体的ID。出于匿名的原因,将出示身份证而不是指定的身份。

基于上述特征的实际意义,我们对其进行如下的处理:

  • children :缺失数据相对较少,我们选择删除携带孩子缺失的数据行。
  • country:因为后续我们可能会用到该数据,所以设置为‘Unknown’。
  • agent:预定的ID在本次数据分析中,不太重要,删除该特征。
  • company:公司的数据在本次数据中,不太重要,而且确实程度过大,直接删除。

相关代码如下:

# inplace表示是否在原数据进行填充
data.dropna(axis=0, how='any',subset=['children'], inplace=True)
# 用Unknown填充'country'为Nan的数据
data.fillna({'country':'Unknown'}, inplace=True)
# 删除'agent','company'的列
data.drop(['agent','company'],axis=1, inplace=True)

📖用户数据探索

在进行了用户数据的基础探索后,接下来就开始对其进行一些分析工作。

📑什么时间预定酒店将会更经济实惠?

作为游客或者用户,我们较为关注的通常是酒店是否经济实惠。在下面的工作中,我们首先提取没有取消的那些订单作为我们分析的数据,然后对其进行一些处理最后进行可视化,代码如下:

import seaborn as sns
# 提取没有取消订单的数据
data_no_canceled = data[data['is_canceled']==0]
# 算出人均价格
data_no_canceled['adr_deal'] = data_no_canceled['adr']/ (data_no_canceled['adults'] + data_no_canceled['children'])
# 对结果进行可视化
ax = sns.lineplot(data=data_no_canceled, x = 'arrival_date_month',y='adr_deal',hue='hotel')
# 设置图片尺寸
ax.figure.set_size_inches(12,6)

结果如下:
在这里插入图片描述
在图中我们可以发现,在七月Resort Hotel价格最高,而在其他时间City Hote的价格会稍高一些。另外,在十一月以及十二月两种酒店的价格是全年最低的,也就是最经济实惠的。

另外,我还探究了不同房型的价格分布情况,代码如下:

# 提取数据并进行排序
roomtype = data_no_canceled[["hotel", "reserved_room_type", "adr_deal"]].sort_values("reserved_room_type")
# 绘制箱线图
ax_box = sns.boxplot(data = roomtype, x = 'reserved_room_type',y='adr_deal',hue='hotel')
ax_box.figure.set_size_inches(12,6)

结果如下:
在这里插入图片描述
可以看到,在图中City Hotel的E房型价格偏高,而Resort Hotel的F房型价格偏高。

📑哪个月份的酒店预订是最繁忙的?

基于上述的分析,我们进一步探索哪个月份的酒店预订是最繁忙的,代码如下:

# 提取用户们到达的日期,并对其进行排序可视化
data_no_canceled['arrival_date_month'].value_counts().sort_values(ascending=False).plot.bar()

结果如下:
在这里插入图片描述
在图中可以看到,5,7,8月是最繁忙的时间,而秋冬季节的酒店人数相对来说较少。

📖商家数据探索

作为商家,较为关心的问题即用户的组成,以便更好的提供服务。另外,做为商家了解不同用户的订购渠道对于进一步的进行市场营销将会有积极的作用。

📑按市场细分的不同预定情况是怎样的?

我们首先基于数据来探索预订酒店的不同国家的人数占比,并进行可视化,代码如下:

import plotly.express as px
# 计算不同国家的百分比
country_data = pd.DataFrame(data['country'].value_counts())
country_data.columns = ['guest_num']
country_data['guest_persent'] = round(country_data['guest_num'] / country_data['guest_num'].sum() * 100,2)

# 对小于一定比例的国家归类
country_data.loc['OTHER','guest_num'] = country_data[country_data['guest_persent'] < 2]['guest_num'].sum()
country_data.loc['OTHER','guest_persent'] = round(country_data.loc['OTHER','guest_num'] / country_data['guest_num'].sum(),2)
# 可视化
country_data.drop(country_data[country_data['guest_persent'] < 0.5].index, inplace=True)
fig = px.pie(country_data,values = 'guest_persent',names = country_data.index)
fig.update_traces(textposition="inside", textinfo="value+percent+label")

结果如下:

在这里插入图片描述
进一步的,我们对不同预订酒店的渠道进行了统计,代码如下:

data_no_canceled['market_segment'].value_counts().plot.bar()

结果如下:
在这里插入图片描述
从图中可以看到,预订的主力军都是旅行社居多。另外,在线预定远比线下预订的数目要多很多。针对商家,可以对线上的广告推荐等进一步的进行策划营销。

📑什么样的人更容易取消预订?

最后,我们希望了解什么样的人更容易取消预订。商家可以针对这部分用户进行服务优化,并进一步的改善酒店的经营模式。在这里,我们准备基于数据进行机器学习模型的构建。

🔖数据编码

在这一步中,我们将对字符型的数据做编码处理,从而更好的适应不同模型,代码如下:

from sklearn import preprocessing
data_to_ml = data.copy()
# 因为我们预测的目标是是否取消了预订,所以删除这两列
data_to_ml.drop(['reservation_status','reservation_status_date'], axis=1, inplace=True)
# 对大部分特征进行编码处理
for col in ['hotel','arrival_date_month','meal','country','market_segment','distribution_channel','customer_type','deposit_type']:
    encoder = preprocessing.LabelEncoder()
    encoder.fit(data_to_ml[col])
    data_to_ml[f'{col}_labeled']  = encoder.transform(data_to_ml[col])
    data_to_ml.drop([col], axis=1, inplace=True)

在这里,我们有一个特殊的操作,即我们根据现有的特征提取了一个新的特征,即酒店预留的房间以及用户预定的是否是相同的。因为如果作为用户发现预定的房间和实际房间不同很可能会取消预订。具体代码如下:

import numpy as np
data_to_ml['is_reserved_assigned_equal'] = np.where(data_to_ml['reserved_room_type']==data_to_ml['assigned_room_type'],1,0)
data_to_ml.drop(['reserved_room_type','assigned_room_type'], axis=1, inplace=True)

🔖特征筛选

在这一步中,我们对所有处理后的数据进行了皮尔逊相关分析并做了可视化,代码如下所示:

import matplotlib.pylab as plt
correlation = data_to_ml.corr('pearson')

f, ax = plt.subplots(figsize = (9, 9))
plt.title('Correlation of Numeric Features with',y=1,size=16)
sns.heatmap(correlation,square = True,  vmax=0.8)

结果如下:
在这里插入图片描述
可以看到,我们所挑选的特征自相关性不算太高可以接受。与此同时,其针对我们所选定的目标is_canceled来说相关性也是可以接受的,所以我们暂时不对其进行处理。

🔖构建模型并预测

在这一部分中,我们构建了主流的模型并使用10折交叉认证对其进行验证,代码如下:


from sklearn import svm
from sklearn.ensemble import RandomForestClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn import model_selection

x_all = data_to_ml.drop('is_canceled',axis=1)
y_all = data_to_ml['is_canceled']

# 为了避免训练时间过长,这里我选择了部分数据集
x_train = x_all.loc[:19999,:]
y_train = y_all[:20000]

model_svm = svm.SVC()
model_knn = KNeighborsClassifier()
model_rf = RandomForestClassifier()

model_dict = {
    'SVM':model_svm,
    'KNeighborsClassifier':model_knn,
    'RandomForestClassifier':model_rf
}
# 训练模型
for model in model_dict:
    model_dict[model].fit(x_train, y_train)
    scores = model_selection.cross_val_score(model_dict[model], X=x_train, y=y_train, verbose=1, cv = 10, scoring='f1')
    print(model, scores.mean())

>>>SVM 0.6480724503120129
>>>KNeighborsClassifier 0.6577070795293697
>>>RandomForestClassifier 0.7363861778481174

可以看到,随机森林的效果是可以接受的,接下来我们对其特征重要性进行可视化。

🔖根据特征重要性得出结论

调用随机森林中自带的特征重要性函数,并对其进行了可视化,代码如下:

# 构建Series让特征重要性和特征名称一一对应
feature_importances_series = pd.Series(list(model_rf.feature_importances_), index = x_all.columns, )
# 对其进行排序
feature_importances_series =feature_importances_series.sort_values(ascending=False)
# 进行可视化
sns.barplot(x = feature_importances_series.values, y = feature_importances_series.index, orient='h')

结果如下:
在这里插入图片描述
如图所示,用户取消预订和逗留时长、用户国籍、到达年份都有很强的相关性。另外,我们提取的特征也是非常重要的,即用户预定的房间和实际的房间不同时,用户将会更容易取消预订。

📍总结

在本文中,我们基于python对酒店预订需求进行分析,并从多种角度对其展开了探索性的工作。这对于养成数据分析习惯有很大的帮助,在实际工作或者学习中还需要不断练习。

感兴趣的朋友们可以自己按照上述步骤进行操作,或在评论区与我讨论。

需要源码的朋友可以私信我进行索取,我们下次再见。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/443844.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

centos8 mysql 主从复制

♥️作者:小刘在C站 ♥️个人主页:小刘主页 ♥️每天分享云计算网络运维课堂笔记,努力不一定有收获,但一定会有收获加油!一起努力,共赴美好人生! ♥️夕阳下,是最美的绽放,树高千尺,落叶归根人生不易,人间真情 目录 Linux centos8

机器学习入门实例-MNIST手写数据集-多分分类错误分析多标签分类多输出分类

多分类 随机梯度下降、随机森林和朴素贝叶斯都可以处理多分类问题&#xff0c;而logistic回归、支持向量机是严格的二分类分类器&#xff0c;但是可以用一些方法将多个二分类分类器组合在一起完成多分类任务。 1. OvR&#xff08;one-versus-the-rest、one-versus-all&#x…

webp格式怎么转换成jpg,3种常用工具方法

在日常办公中&#xff0c;我们经常需要在网上找到一些图片进行编辑。但有时候我们会遇到Webp格式的图片&#xff0c;而有些软件无法直接编辑它们。Webp是一种由谷歌开发的图像文件格式&#xff0c;它提供了有损压缩和无损压缩(可逆压缩)的功能&#xff0c;近年来&#xff0c;它…

Kafka基础篇学习笔记整理

Kafka基础篇学习笔记整理 生产者数据发送流程批量与定时发送缓冲区大小send发送消息消息可靠性发布确认机制重试机制 消息顺序性问题如何避免重试导致消息顺序错乱自定义拦截器自定义序列化器自定义分区器幂等与事务kafka实现幂等kafka实现事务事务的隔离级别使用演示 消费者重…

【状态估计】用于描述符 LTI 和 LPV 系统的分析、状态估计和故障检测的算法(Matlab代码实现)

&#x1f4a5; &#x1f4a5; &#x1f49e; &#x1f49e; 欢迎来到本博客 ❤️ ❤️ &#x1f4a5; &#x1f4a5; &#x1f3c6; 博主优势&#xff1a; &#x1f31e; &#x1f31e; &#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 …

免费文案生成器-免费文案改写神器

推荐一款高效免费自动写作软件&#xff0c;让你的写作效率飞升&#xff01; 写作&#xff0c;对于众多的从业者或学生来说都是必不可少的工作内容。然而&#xff0c;许多人在写作时遇到了各种各样的困难&#xff0c;例如缺乏灵感、引用不足、缺乏逻辑性等等。为了解决这些问题…

Linux DHCP服务

DHCP 作用 DHCP动态主机配置协议作为服务端负责集中给客户端分配各种网络地址参数(主要包括IP地址、子网掩码、广播地址、默认网关地址、DNS服务器地址) 传输协议端口 服务端 UDP 67端口 客户端 UDP 68端口 工作原理 1) 客户端广播发送DISCOVER报文寻找服务端 2) 服务端广播发…

Unity - 带耗时 begin ... end 的耗时统计的Log - TSLog

CSharp Code // jave.lin 2023/04/21 带 timespan 的日志 &#xff08;不帶 log hierarchy 结构要求&#xff0c;即&#xff1a; 不带 stack 要求&#xff09;using System; using System.Collections.Generic; using System.IO; using UnityEditor; using UnityEngine;public…

Qt 学生信息数据库管理

1 添加样式表 我们采用了样式表 通过添加Qt resources文件 添加前缀 添加文件&#xff0c;将我们的图标进行添加 2 拖动部件 用到的部件 Label 标签Pushbutton 按钮table view 视图LineEdit 输入框 3 程序编写 1 配置sql环境 在 pro文件中 添加 连接数据库跟访问数据…

Qt模型视图结构

一.模型视图介绍 1.Model/View(模型/视图结构) 视图(View)是显示和编辑数据的界面组件&#xff0c; 模型(Model)是视图和原始数据之间的接口 2.视图组件有:QListView QTreeView QTableView&#xff0c;QColumnView&#xff0c;QHeaderView 模型组件有:QStringListM…

MyBatis详解(2)

8、自定义映射resultMap 8.1、resultMap处理字段和属性的映射关系 若字段名和实体类中的属性名不一致&#xff0c;则可以通过resultMap设置自定义映射 <!--resultMap&#xff1a;设置自定义映射属性&#xff1a;id&#xff1a;表示自定义映射的唯一标识type&#xff1a;查询…

PCIE_DMA实例二:xapp1052的EDK仿真

目录 一&#xff1a;前言 二&#xff1a;前期准备 三&#xff1a;操作步骤 四&#xff1a;仿真结果 五&#xff1a;总结 一&#xff1a;前言 对于有的同学&#xff0c;想要学习基于FPGA的PCIe DMA控制器设计&#xff0c;但是手上没有合适的Xilinx开发板&#xff0c;而且xap…

ETCD(五)写请求执行过程

写请求过程 客户端执行写请求指令 etcdctl put hello world —endpoints 192.168.1.1:12379执行流程&#xff1a; 首先客户端通过负载均衡选择一个etcd节点发起gRPC put方法调用&#xff1b;服务器收到请求后经过gRPC拦截器、Quota模块校验&#xff0c;进入KV Server模块&am…

「物联网时代的新选择」漫途科技推出装配式物联网服务,轻松实现项目落地

随着物联网技术的不断发展&#xff0c;越来越多的企业开始重视物联网系统的应用。然而&#xff0c;在物联网时代&#xff0c;鱼龙混杂&#xff0c;小品牌厂商层出不穷&#xff0c;质量参差不齐&#xff0c;这为系统集成商寻找靠谱的供应商伙伴带来了极大的挑战。 一、如何找靠谱…

Nacos配置中心的配置是怎么加载到spring容器的?

首先看到 org.springframework.boot.SpringApplication#applyInitializers 这个方法。 protected void applyInitializers(ConfigurableApplicationContext context) {for (ApplicationContextInitializer initializer : getInitializers()) {Class<?> requiredType G…

单链表C语言实现

链表就是许多节点在逻辑上串起来的数据存储方式 是通过结构体中的指针将后续的节点串联起来 typedef int SLTDataType;//数据类型 typedef struct SListNode//节点 {SLTDataType data;//存储的数据struct SListNode* next;//指向下一个节点地址的指针 }SLTNode;//结构体类型的…

设计模式(GOF)之我见(0)——UML

这里直接梳理画类图时的几个类关系。 类图的语法和功能 关系说明举例依赖&#xff08;Dependency) 偶然的&#xff0c;陌生的。 对类B进行修改会影响到A。 例如&#xff1a;问路时&#xff0c;路人甲给路人乙带路&#xff0c;路人甲的指引必然会影响到路人乙&#xff0c;但是…

在ROS2中使用奥比中光(ORBBEC)的AstraPro深度相机

0.效果演示 1.下载SDK 到官网下载OpenNI2_SDK 记得是下载这个OpenNI2_SDK,而不是下载那个Orbbec_SDK. 2.拷贝至自定义目录 拷贝到你的ubuntu的一个文件夹中&#xff0c;并解压得到 ros2_astra_camera 文件夹 然后新建一个ros2_ws文件夹&#xff0c;再在ros2_ws文件夹中新建…

矩阵链相乘的乘法次数(动态规划)

Description 设 A1, A2, …, An 为矩阵序列&#xff0c;Ai 是阶为 Pi − 1 * Pi 的矩阵 i  1, 2, …, n.试确定矩阵的乘法顺序&#xff0c;使得计算 A1A2…An 过程中元素相乘的总次数最少.Input 多组数据第一行一个整数 n(1≤n≤300) &#xff0c;表示一共有 n 个矩…

真题详解(计算机知识)-软件设计(五十四)

真题详解&#xff08;归并&#xff09;-软件设计&#xff08;五十三)https://blog.csdn.net/ke1ying/article/details/130254861 若无条件转移汇编指令采用直接寻址&#xff0c;则该指令功能是将指令中的地址码送入_____? PC&#xff08;程序计数器&#xff09; 程序计数器&…