一、 选题的背景

  当今已经是大数据的时代,随着数据分析工具和技术的不断改进,越来越多的公司和组织开始采用大数据分析来改善业务流程、降低成本、提高效率等。因此,掌握大数据分析技能也可以为个人的职业发展带来很大的好处。

  我分析的目标是酒店预订需求数据分析,这其中包括了解市场趋势、优化决策过程、改善业务流程、降低成本、提高效率等。

二、 大数据分析设计方案

  1、本数据集的数据内容与数据特征分析

列名

数据类型

含义

hotel

object

包含H1和H2,H1指假日酒店;H2指城市酒店

is_canceled

int64 

1代表取消,O代表不取消

lead_time

int64 

入住前多长时间预定

arrival_date_year

int64 

入住年

arrival_date_month

object

入住月份

arrival_date_week_number

int64

在第几周入住

arrival_date_day_of_month

int64

在月份中几号入住

stays_in_weekend_nights

int64

在周末住几晚

stays_in_week_nights

int64

在一周之内住几晚

adults

int64

成年人预订人数

children

float64

儿童预订人数

babies

int64

婴儿预订人数

meal

object

不同种类餐食预订情况

country

object

不同国家简写

market_segment

object

市场划分,分为旅行社代理人和包价旅游承包

distribution_channel

object

分布渠道,同market_segment

is_repeated_guest

int64

以前是否预订过

previous_cancellations

int64

这次预订以前取消的次数

previous_bookings_not_canceled

int64

这次预订以前没有取消的次数

reserved_room_type

object

预订房型,类别较多,以字母A-P划分

assigned_room_type

object

入住的房型,同reserved_room_type

booking_changes

int64

变更预订次数

deposit_type

object

押金类型

agent

object

代理商ID

company

object

公司ID

days_in_waiting_list

int64

证实预订前等待的天数

customer_type

object

顾客类别

adr

float64

平均每日价格

required_car_parking_spaces

int64

需要的停车位

total_of_special_requests

int64

特殊需求数

reservation_status

object

订单状态

reservation_status_date

object

显示订单状态日期

  2、数据分析的课程设计方案概述

    1)  数据收集:如何收集大量数据。

      解决方案:通过和鲸社区和Kaggle查找需要的数据。

    2) 大数据分析:如何结合大数据生成的图表进行分析

           解决方案:结合实际情况,如地理位置,活动节日等进行实际推断。

三、 数据分析步骤

  1、 数据源

    该数据集来自kaggle

    网址:https://www.kaggle.com/code/swetarajsinha/hotel-bookings/data

  2、 数据清洗

    检查是否能完整显示各行各列的数据

1 #设置显示所有列
2 pd.set_option('display.max_columns', None)
3 
4 #读取文件,并显示所有的数据
5 data=pd.read_csv('hotel_bookings.csv')
6 df=data.copy()
7 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

children

babies

meal

country

market_segment

distribution_channel

is_repeated_guest

previous_cancellations

previous_bookings_not_canceled

reserved_room_type

assigned_room_type

booking_changes

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

0.0

0

BB

PRT

Direct

Direct

0

0

0

C

C

3

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

0.0

0

BB

PRT

Direct

Direct

0

0

0

C

C

4

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

0.0

0

BB

GBR

Direct

Direct

0

0

0

A

C

0

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

0.0

0

BB

GBR

Corporate

Corporate

0

0

0

A

A

0

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

0.0

0

BB

GBR

Online TA

TA/TO

0

0

0

A

A

0

No Deposit

240.0

NaN

0

Transient

98.0

0

1

Check-Out

2015-07-03

    检查数据中是否有空数据

1 '''
2 #检查数据中缺少的值
3 #1、先用 isnull 函数会返回一个布尔型数据框,其中每个元素都表示对应的数据是否为空。
4 #2、接着使用 sum 函数对数据为空的所有元素进行求和。
5 #3、使用布尔索引判断大于 0 的值,就能得到数据中存在缺失的值。
6 '''
7 df.isnull().sum()[df.isnull().sum()>0]

 

    显示结果如下:

酒店订单管理系统 架构 酒店订单数据分析_数据

    对有空数据的列进行数据清洗,并检查是否还存在空数据

1 #进行数据清洗
 2 #将 agent 列中选择所有缺失值的值。并将这些值更新为 'No agent'
 3 df.loc[df.agent.isnull()==False,'agent']='Agent'
 4 df.agent.fillna('No agent',inplace=True)
 5 #使用 Unknown (未知)来填充 country (国家)列缺少的值
 6 df.country.fillna('Unknown',inplace=True)
 7 #使用 0 来填充 children (儿童预定人数)列缺少的值
 8 df.children.fillna(0,inplace=True)
 9 '''
10 #对 company (公司ID)列进行更新
11 #某些行中,细分市场或分销渠道被指定为公司,其中公司行为空,将用 Corporate (公司)填充这些空值
12 #将在公司栏中填写公司的非缺失值
13 #用 Individuals (个人)填充公司列中剩余的缺失值
14 '''
15 df.loc[((df.market_segment=='Corporate') | (df.distribution_channel=='Corporate')) & (df.company.isnull()),'company']='Corporate'
16 df.loc[df.company.isnull()==False,'company']='Corporate'
17 df.company.fillna('Individuals',inplace=True)
18 
19 #查看数据之中是否还存在缺失值
20 df.isnull().sum()

 

    显示结果如下:

酒店订单管理系统 架构 酒店订单数据分析_酒店订单管理系统 架构_02

    删除重复冗余的数据,并对每个国家进行归纳整理,将每个国家归入对应的大陆上

1 #删除重复数据
 2 df=df.drop_duplicates(keep='first').reset_index().drop(columns='index')
 3 #将数据类型更正为 object 方便进行变量分析
 4 df.arrival_date_year=df.arrival_date_year.astype(object)
 5 #列出数据中所有国家的简称
 6 df.country.unique()
 7 
 8 #将每个国家归入对应的大陆上
 9 
10 europe=['PRT','GBR','ESP','IRL','FRA','ROU','NOR','POL','DEU','BEL','CHE','GRC','ITA','NLD','DNK','RUS','SWE','EST',
11        'CZE','FIN','LUX','SVN','ALB','UKR','SMR','LVA','SRB','AUT','BLR','LTU','TUR','HUN','HRV','GEO','AND','SVK',
12        'MKD','BIH','BGR','MLT','ISL','MCO','LIE','MNE']
13 
14 north_a=['USA','MEX','PRI','CRI','CUB','HND','NIC','GAB','PAN','SLV','GTM']
15 
16 south_a=['ARG','BRA','CHL','URY','COL','VEN','SUR','PER','ECU','BOL','PRY','GUY']
17 
18 asia=['OMN','CN','IND','CHN','ISR','KOR','ARE','HKG','IRN','CYP','KWT','MDV','KAZ','PAK','IDN','LBN','PHL','AZE','BHR',
19      'THA','MYS','ARM','JPN','LKA','JOR','SYR','SGP','SAU','VNM','QAT','UZB','NPL','MAC','TWN','IRQ','KHM','BGD','TJK',
20      'TMP','MMR','LAO']
21 
22 africa=['MOZ','BWA','MAR','ZAF','AGO','ZMB','ZWE','DZA','TUN','CAF','NGA','SEN','SYC','CMR','MUS','COM','UGA','CIV',
23        'BDI','EGY','MWI','MDG','TGO','DJI','STP','ETH','RWA','BEN','TZA','GHA','KEN','GNB','BFA','LBY','MLI','NAM',
24        'MRT','SDN','SLE']
25 
26 australia=['AUS']
27 
28 Others=['CYM','CPV','JAM','GIB','JEY','GGY','FJI','NZL','DOM','PLW','BHS','KNA','IMN','VGB','GLP','UMI','MYT','FRO',
29        'BRB','ABW','AIA','DMA','PYF','LCA','ATA','ASM','NCL','KIR','ATF']
30 
31 unk=['Unknown']
32 
33 #将国家/地区列放入二进制
34 def country_bin(x):
35     if x in europe:
36         return 'Europe'
37     elif x in north_a:
38         return 'North America'
39     elif x in south_a:
40         return 'South America'
41     elif x in asia:
42         return 'Asia'
43     elif x in africa:
44         return 'Africa'
45     elif x in australia:
46         return 'Australia'
47     elif x in Others:
48         return 'Others'
49     elif x in unk:
50         return 'Unknown'
51 df.country=df.country.apply(country_bin) 
52 
53 #所有国家分配成各个地区
54 df.country.unique()

 

   3、大数据分析过程

    通过pandas.crosstab()函数来生成数据表,方便查看数据间的关系。

    #绘制酒店取消预订数量表

1 tbl=pd.crosstab(df.hotel,df.is_canceled,margins=True)
2 tbl

 

 

    显示结果如下:

is_canceled

0

1

All

hotel

 

 

 

City Hotel

37373

16047

53420

Resort Hotel

25985

7974

33959

All

63358

24021

87379

    #添加一列 cancel_percent (取消预订的百分比)来显示取消的预订占总预订的百分比

1 tbl['cancel_percent']=tbl[1]*100/tbl['All']
2 tbl

 

     显示结果如下:

is_canceled

0

1

All

cancel_percent

hotel

 

 

 

 

City Hotel

37373

16047

53420

30.039311

Resort Hotel

25985

7974

33959

23.481257

All

63358

24021

87379

27.490587

    #绘制酒店取消预订柱状图

1 pd.crosstab(df.hotel, df.is_canceled, values=df.is_canceled, aggfunc='count', normalize=True).plot.bar()
2 plt.title('酒店取消预订情况')
3 plt.ylabel('取消预订比例')
4 plt.xlabel('酒店类型')
5 plt.show()

     显示结果如下:

酒店订单管理系统 架构 酒店订单数据分析_大数据分析_03

 

    分析:这里可以看出来,City Hotel(城市酒店)取消的人数更多,相比较于Resort Hotel(假日酒店)多出了6.5个百分点,除去正常超额预订的情况,City Hotel的取消率还是过高,可能是因为城市酒店位置优越,方便前往商务场所或者旅游景点。此外,城市酒店的价格可能比假日酒店的价格更容易接受。

 

     #通过 lead_time (入住前多长时间预订)列绘制直方图

1 sns.distplot(df.lead_time)
2 plt.show()

 

      显示结果如下:

酒店订单管理系统 架构 酒店订单数据分析_数据_04

#绘制城市酒店和假日酒店的盒图
1 #通过 is_canceled (是否取消预订)列和 lead_time (入住前多长时间预订)列绘制城市酒店的盒图
2 sns.boxplot(x='is_canceled',y='lead_time',data=df.loc[df.hotel=='City Hotel'])
3 plt.show()
4 
5 
6 #通过 is_canceled (是否取消预订)列和 lead_time (入住前多长时间预订)列绘制假日酒店的盒图
7 sns.boxplot(x='is_canceled',y='lead_time',data=df.loc[df.hotel=='Resort Hotel'])
8 plt.show()

      显示结果如下:

酒店订单管理系统 架构 酒店订单数据分析_酒店订单管理系统 架构_05

酒店订单管理系统 架构 酒店订单数据分析_大数据分析_06

 

    分析:通过lead_time (入住前多长时间预订)与酒店取消预订绘制两个盒图,发现Resort Hotel(右)比City Hotel(左)取消预订最长提前期更高,但City Hotel的平均取消预订更高,可能是因为City Hotel的客户群更为多样化,其中可能包括许多商务旅客。这些商务旅客可能会因为工作原因或其他突发事件而不得不取消预订。

 

    #绘制两个酒店每年预订的柱状图

1 plt.rcParams['figure.figsize']=[8,5]
2 sns.countplot(x='arrival_date_year',data=df,hue='hotel')
3 plt.xlabel('年份')
4 plt.ylabel('预订数量')
5 plt.title('每年的预订')
6 plt.show()

 

       显示结果如下:

酒店订单管理系统 架构 酒店订单数据分析_酒店订单管理系统 架构_07

    分析:从图中可以看出2016年的预订量是最高的,而2015年是最少的,可能2015年后市场需求增加、2015年后酒店更新和建立数量增加等。

 

     # 显示全年取消率的表

1 tbl=pd.crosstab(df.arrival_date_year,df.is_canceled,margins=True)
2 tbl
3 #添加一列 cancel-percent (取消预订的百分比)来显示取消的预订占总预订的百分比
4 tbl['cancel-percent']=tbl[1]*100/tbl['All']
5 tbl

 

       显示结果如下:

is_canceled

0

1

All

cancel-percent

arrival_date_year

 

 

 

 

2015

10605

2702

13307

20.305103

2016

31178

11207

42385

26.440958

2017

21575

10112

31687

31.912141

All

63358

24021

87379

27.490587

     #绘制全年取消率柱状图

1 tbl.drop('All',axis=0)['cancel-percent'].plot.bar()
2 plt.xticks(rotation=0)
3 plt.xlabel('Year')
4 plt.ylabel('Cancellation %')
5 plt.title('2015-2017年取消率')
6 plt.show()

 

        显示结果如下:

酒店订单管理系统 架构 酒店订单数据分析_Corporate_08

    #绘制每个年份的取消预订的数量所占所有取消预订的总数的比例。

df[df.is_canceled==1]['arrival_date_year'].value_counts()/len(df[df.is_canceled==1])

       显示结果如下:

酒店订单管理系统 架构 酒店订单数据分析_Corporate_09

    分析:根据图标显示发现,酒店的预订数量和取消率连年增加,说明随着年份增加,酒店市场需求也再增加,随着市场的增加客户的选择更多,当发现有更加好的酒店时,就更容易取消预订过的酒店。也有可能是随着预订数量的增加,酒店进行了房间超售,导致客户不满或无房可住,导致预订取消率增加。

 

    #绘制每月的预订数量

1 plt.rcParams['figure.figsize']=[8,5]
2 sns.countplot(x='arrival_date_month',data=df,order=df.arrival_date_month.value_counts().index)
3 plt.title('每月预订数量 ')
4 plt.xlabel('预订月份')
5 plt.ylabel('预订数量')
6 plt.xticks(rotation=60,ha='right')
7 plt.show()

 

         显示结果如下:

酒店订单管理系统 架构 酒店订单数据分析_数据_10

    #绘制每月预订数量

1 plt.rcParams['figure.figsize']=[8,5]
2 sns.countplot(x='arrival_date_month',data=df,order=df.arrival_date_month.value_counts().index,hue='hotel')
3 plt.title('每月预订数量 ')
4 plt.xlabel('Booking Month')
5 plt.ylabel('Number of Bookings')
6 plt.xticks(rotation=60,ha='right')
7 plt.show()

 

        显示结果如下:

酒店订单管理系统 架构 酒店订单数据分析_酒店订单管理系统 架构_11

    #显示每个月预订数量

1 tbl=pd.crosstab(df.arrival_date_month,df.is_canceled,margins=True)
2 tbl['cancel_percent']=tbl[1]*100/tbl['All']
3 tbl

 

        显示结果如下:

is_canceled

0

1

All

arrival_date_month

 

 

 

April

5498

2409

7907

August

7633

3621

11254

December

3751

1378

5129

February

4682

1415

6097

January

3654

1038

4692

July

6858

3198

10056

June

5411

2353

7764

March

5681

1830

7511

May

5912

2442

8354

November

3939

1053

4992

October

5292

1642

6934

September

5047

1642

6689

All

63358

24021

87379

    #将上表中的取消预订的百分比进行绘制

 

1 tbl.drop('All',axis=0)['cancel_percent'].plot.bar()
2 plt.title('每个月取消预订百分比')
3 plt.xlabel('月份')
4 plt.ylabel('取消预订百分比(%)')
5 plt.show()

 

 

 

      显示结果如下:

酒店订单管理系统 架构 酒店订单数据分析_数据_12

    分析:与其他月份相比,8月和7月的预定量是最高的,这期间一般是学校假期,学生群体更容易去其他地方旅游度假或参加聚会活动,所以假期也是假期预订量的关键。但通过后续的取消预订百分比图发现,7、8月份也是取消率最高的月份,根据上一个酒店会超售的分析,再次表明了,在节假日期间,酒店的预订量会过多和匆忙。

 

#绘制第几周入住的柱状图

 

1 plt.figure(figsize=(10,15))
2 sns.countplot(x='arrival_date_week_number',data=df)
3 plt.title('每周入住数量')
4 plt.xticks(rotation='vertical')
5 plt.xlabel('每年的周数')
6 plt.ylabel('数量')
7 plt.show()

 

 

 

      显示结果如下:

酒店订单管理系统 架构 酒店订单数据分析_大数据分析_13

    分析:不难发现,第33周的预订量是最高的,推算一下是在8月份附近,进一步支持了8月份节假日举行活动和旅游度假的说法。还看到临近年底与过年前夕,预订数量明显减少,特别是在51周,是预订量最低的一周,根据推算,是在12月份中旬,在国外,这个日子最接近圣诞节,说明人们在这一周会进行圣诞节的准备活动,不会过多的在意酒店预订。

 

    #绘制周末入住持续天数

1 plt.figure(figsize=(7,7))
2 sns.distplot(df.stays_in_weekend_nights)
3 plt.title('周末入住持续天数')
4 plt.xlabel('周末入住天数')
5 plt.ylabel('密度')
6 plt.show()

 

       显示结果如下:

酒店订单管理系统 架构 酒店订单数据分析_大数据分析_14

    分析:大多数人在酒店停留时间较短,通常是0-3天(0天是酒店的钟点房)。由此可以说明酒店的受众类型是短期旅行度假和临时居住的类型,也有一些记录是停留时间更长,这可能是因为人们出差或进行比较长时间的项目。

 

    #通过 hotel (酒店)列和stays_in_weekend_nights(周末入住天数)列绘制盒图

1 plt.figure(figsize=(7,7))
2 sns.boxplot(x='hotel',y='stays_in_weekend_nights',data=df)
3 plt.show()

 

        显示结果如下:

酒店订单管理系统 架构 酒店订单数据分析_数据_15

    分析:通过盒图发现,两个酒店在周末入住天数其实差不多,所以,周末在City Hotel 和Resort Hotel 住的人只是进行短住,一般持续一两天,长期居住的人较少。

 

    #绘制成年人预定人数入住图

1 plt.figure(figsize=(5,5))
2 sns.distplot(df.loc[(df.stays_in_week_nights==0) & (df.stays_in_weekend_nights==0)]['adults'])
3 plt.title('成年人预订人数图')
4 plt.ylabel('密度')
5 plt.xlabel('成年人预订人数')
6 plt.show()

 

         显示结果如下:

酒店订单管理系统 架构 酒店订单数据分析_大数据分析_16

     分析:由图片可以得知,预订大部分人是单人和双人,只有少数的未成年人和极少数有三个人的预订。人数最多的是双人预订,大部分可能是夫妻和情侣入住,大多可能是以休闲或旅游为主。

 

    #绘制婴儿预订入住图

 

1 plt.figure(figsize=(5,5))
2 sns.distplot(df.babies)
3 plt.title('婴儿预订入住图')
4 plt.ylabel('密度')
5 plt.xlabel('婴儿数量')
6 plt.show()

 

 

 

          显示结果如下:

酒店订单管理系统 架构 酒店订单数据分析_酒店订单管理系统 架构_17

    分析:由婴儿预订入住图可以明确的看出,基本上入住的都是没有婴儿的人(排除可能将婴儿放置在亲戚或其他的可能),只有极少数人会带领一个婴儿入住酒店。表明,来入住酒店的人群多是公司旅行、单人旅行、情侣旅行等,只有极少数由婴儿的家庭来旅行。

 

    #绘制国家地区频率分布图

1 plt.figure(figsize=(8,8))
2 sns.countplot(x='country',data=df)
3 plt.title('国家地区频率分布')
4 plt.xticks(rotation=60,ha='right')
5 plt.ylabel('数量')
6 plt.xlabel('国家地区')
7 plt.show()

 

          显示结果如下:

酒店订单管理系统 架构 酒店订单数据分析_数据_18

    #生成国家地区是否取消预订表

1 tbl=pd.crosstab(df.country,df.is_canceled,margins=True)
2 #添加一列 cancel-percent (取消预订的百分比)来显示取消的预订占总预订的百分比
3 tbl['cancel_percent']=tbl[1]*100/tbl['All']
4 tbl

 

    显示结果如下:

 

is_canceled

0

1

All

country

 

 

 

Africa

559

436

995

Asia

2286

1141

3427

Australia

286

92

378

Europe

56573

20944

77517

North America

1531

474

2005

Others

106

53

159

South America

1599

847

2446

Unknown

418

34

452

All

63358

24021

87379

    分析:由图可以得出,大部分来酒店的是欧洲地区的人,可以推断,此数据来源于欧洲,也有少数亚洲和其他地区的人来旅游入住。酒店的消费主力是欧洲人,可以对酒店进行针对性改造,更加吸引欧洲人入住。

 

    #绘制国家地区取消预订百分比图

1 plt.figure(figsize=(7,7))
2 tbl.drop('All',axis=0)['cancel_percent'].plot.bar()
3 plt.title('国家地区取消预订百分比图')
4 plt.xticks(rotation=60,ha='right')
5 plt.ylabel('取消预订百分比(%)')
6 plt.xlabel('国家地区')
7 plt.show()

 

    显示结果如下:

酒店订单管理系统 架构 酒店订单数据分析_酒店订单管理系统 架构_19

    分析:从图中可以看出,Africa (非洲)的取消率是最高的,应该是源于签证的问题,因为欧盟有一些严格的规定(欧洲的国家取消比例要低很多),在上图中可以看出,除了未知地区,North America (北美)客户的取消率是最低的,这可能是北约的原因。

 

    #绘制市场划分图

 

1 plt.rcParams['figure.figsize']=[7,7]
2 sns.countplot(x='market_segment',data=df)
3 plt.xticks(rotation=60,ha='right')
4 plt.title('市场划分图')
5 plt.ylabel('数量')
6 plt.xlabel('市场划分')
7 plt.show()

 

 

 

     显示结果如下:

酒店订单管理系统 架构 酒店订单数据分析_酒店订单管理系统 架构_20

    #显示市场划分数量表

1 tbl=pd.crosstab(df.market_segment,df.is_canceled,margins=True)
2 #添加一列 cancel-percent (取消预订的百分比)来显示取消的预订占总预订的百分比
3 tbl['cancel_percent']=tbl[1]*100/tbl['All']
4 tbl

 

      显示结果如下:

is_canceled

0

1

All

market_segment

 

 

 

Aviation

182

45

227

Complementary

614

88

702

Corporate

3698

510

4208

Direct

10067

1737

11804

Groups

3606

1335

4941

Offline TA/TO

11822

2060

13882

Online TA

33369

18244

51613

Undefined

0

2

2

All

63358

24021

87379

    #绘制市场取消率图

 

1 tbl.drop('All',axis=0)['cancel_percent'].plot.bar()
2 plt.title('市场取消率')
3 plt.xticks(rotation=60,ha='right')
4 plt.ylabel('取消预订百分比(%)')
5 plt.xlabel('市场划分')
6 plt.show()

 

 

 

       显示结果如下:

酒店订单管理系统 架构 酒店订单数据分析_数据_21

    分析:由市场划分图可以发现,绝大多数的记录是通过Online TA(在线旅行代理商)获得的,这表明在线旅行代理商在欧盟拥有强大的网络,在网络上有完善的预约流程。还发现有一些 Complementary(补充)的记录,这表示可能是酒店方面有报销或补偿的政策。从市场取消率可以发现 Undefined(未定义)的取消率是最高的,达到了百分百。这很不正常,查看市场划分数量表后发现,未定义数量有2条记录,这可能是由于系统错误,导致多了两条错误,并全部让其取消了。排除Undefined的记录后发现,Online TA的取消率是最高的,这表明,人们在看到网络上的酒店可能跟实际不符,可能导致预订取消的情况。

 

#绘制市场分布渠道图

1 sns.countplot(x='distribution_channel',data=df)
2 plt.title('市场分布渠道图')
3 plt.ylabel('数量')
4 plt.xlabel('市场分布渠道')
5 plt.show()

 

        显示结果如下:

酒店订单管理系统 架构 酒店订单数据分析_酒店订单管理系统 架构_22

    #显示市场分布渠道数量表

1 tbl=pd.crosstab(df.distribution_channel,df.is_canceled,margins=True)
2 ##添加一列 cancel-percent (取消预订的百分比)来显示取消的预订占总预订的百分比
3 tbl['cancel_percent']=tbl[1]*100/tbl['All']
4 tbl

 

       显示结果如下:

is_canceled

0

1

All

cancel_percent

distribution_channel

 

 

 

 

Corporate

4429

648

5077

12.763443

Direct

11063

1925

12988

14.821374

GDS

145

36

181

19.889503

TA/TO

47720

21408

69128

30.968638

Undefined

1

4

5

80.000000

All

63358

24021

87379

27.490587

    #绘制市场分布渠道百分比图

 

1 tbl.drop('All',axis=0)['cancel_percent'].plot.bar()
2 plt.title('市场分布渠道百分比图')
3 plt.ylabel('取消预订百分比(%)')
4 plt.xlabel('分布渠道')
5 plt.show()

 

 

 

         显示结果如下:

 

酒店订单管理系统 架构 酒店订单数据分析_数据_23

    分析:在市场分布渠道图中可以发现,TA/TO(旅行代理商/旅行社)的预订量是最高的,说明酒店与TA/TO的联合合作。在市场分布百分比图中发现Undefined(未定义)的取消率是最高的,查看市场分布渠道数量表后发现,Undefined的数量为5条。将Undefined排除后,发现TA/TO的取消率是最高的,Corporate(公司)的取消率是最低的。这可能是因为公司预订是为了业务目的安排的,因此取消的风险可能较小,公司旅行还可能会有更多的提前安排和计划,这可能会使取消的可能性更小。

 

  4、 完整代码

1 #导入所需要的库
  2 import numpy as np
  3 import pandas as pd
  4 from matplotlib import pyplot as plt
  5 import seaborn as sns
  6 import warnings
  7 warnings.filterwarnings('ignore')
  8 import scipy.stats as stats
  9 from sklearn.model_selection import train_test_split
 10 from sklearn.ensemble import RandomForestClassifier
 11 from lightgbm import LGBMClassifier
 12 from sklearn.metrics import accuracy_score,classification_report,confusion_matrix
 13 from sklearn.metrics import ConfusionMatrixDisplay,f1_score,recall_score,precision_score
 14 
 15 #设置显示所有列
 16 pd.set_option('display.max_columns', None)
 17 
 18 #读取文件,并显示所有的数据
 19 data=pd.read_csv('hotel_bookings.csv')
 20 df=data.copy()
 21 df.head()
 22 
 23 #显示摘要信息
 24 df.info()
 25 
 26 #对数据进行统计
 27 df.describe()
 28 
 29 #计算每对数据列的相关系数
 30 df.corr()
 31 '''
 32 #检查数据中缺少的值
 33 #1、先用 isnull 函数会返回一个布尔型数据框,其中每个元素都表示对应的数据是否为空。
 34 #2、接着使用 sum 函数对数据为空的所有元素进行求和。
 35 #3、使用布尔索引判断大于 0 的值,就能得到数据中存在缺失的值。
 36 '''
 37 df.isnull().sum()[df.isnull().sum()>0]
 38 
 39 #对 Agent (代理商ID)列进行数据清洗
 40 #将 agent 列中选择所有缺失值的值。并将这些值更新为 'No agent'
 41 df.loc[df.agent.isnull()==False,'agent']='Agent'
 42 df.agent.fillna('No agent',inplace=True)
 43 
 44 #检查数据中缺少的值
 45 df.isnull().sum()[df.isnull().sum()>0]
 46 
 47 #使用 Unknown (未知)来填充 country (国家)列缺少的值
 48 df.country.fillna('Unknown',inplace=True)
 49 #检查数据中缺少的值
 50 df.isnull().sum()[df.isnull().sum()>0]
 51 
 52 #使用 0 来填充 children (儿童预定人数)列缺少的值
 53 df.children.fillna(0,inplace=True)
 54 #检查数据中缺少的值
 55 df.isnull().sum()[df.isnull().sum()>0]
 56 
 57 '''
 58 #对 company (公司ID)列进行更新
 59 #某些行中,细分市场或分销渠道被指定为公司,其中公司行为空,将用 Corporate (公司)填充这些空值
 60 #将在公司栏中填写公司的非缺失值
 61 #用 Individuals (个人)填充公司列中剩余的缺失值
 62 '''
 63 df.loc[((df.market_segment=='Corporate') | (df.distribution_channel=='Corporate')) & (df.company.isnull()),'company']='Corporate'
 64 df.loc[df.company.isnull()==False,'company']='Corporate'
 65 df.company.fillna('Individuals',inplace=True)
 66 
 67 #查看数据之中是否存在缺失值
 68 df.isnull().sum()
 69 
 70 #删除重复数据
 71 df=df.drop_duplicates(keep='first').reset_index().drop(columns='index')
 72 #将数据类型更正为 object 方便进行变量分析
 73 df.arrival_date_year=df.arrival_date_year.astype(object)
 74 #列出数据中所有国家的简称
 75 df.country.unique()
 76 
 77 #将每个国家归入对应的大陆上
 78 
 79 europe=['PRT','GBR','ESP','IRL','FRA','ROU','NOR','POL','DEU','BEL','CHE','GRC','ITA','NLD','DNK','RUS','SWE','EST',
 80        'CZE','FIN','LUX','SVN','ALB','UKR','SMR','LVA','SRB','AUT','BLR','LTU','TUR','HUN','HRV','GEO','AND','SVK',
 81        'MKD','BIH','BGR','MLT','ISL','MCO','LIE','MNE']
 82 
 83 north_a=['USA','MEX','PRI','CRI','CUB','HND','NIC','GAB','PAN','SLV','GTM']
 84 
 85 south_a=['ARG','BRA','CHL','URY','COL','VEN','SUR','PER','ECU','BOL','PRY','GUY']
 86 
 87 asia=['OMN','CN','IND','CHN','ISR','KOR','ARE','HKG','IRN','CYP','KWT','MDV','KAZ','PAK','IDN','LBN','PHL','AZE','BHR',
 88      'THA','MYS','ARM','JPN','LKA','JOR','SYR','SGP','SAU','VNM','QAT','UZB','NPL','MAC','TWN','IRQ','KHM','BGD','TJK',
 89      'TMP','MMR','LAO']
 90 
 91 africa=['MOZ','BWA','MAR','ZAF','AGO','ZMB','ZWE','DZA','TUN','CAF','NGA','SEN','SYC','CMR','MUS','COM','UGA','CIV',
 92        'BDI','EGY','MWI','MDG','TGO','DJI','STP','ETH','RWA','BEN','TZA','GHA','KEN','GNB','BFA','LBY','MLI','NAM',
 93        'MRT','SDN','SLE']
 94 
 95 australia=['AUS']
 96 
 97 Others=['CYM','CPV','JAM','GIB','JEY','GGY','FJI','NZL','DOM','PLW','BHS','KNA','IMN','VGB','GLP','UMI','MYT','FRO',
 98        'BRB','ABW','AIA','DMA','PYF','LCA','ATA','ASM','NCL','KIR','ATF']
 99 
100 unk=['Unknown']
101 
102 #将国家/地区列放入二进制
103 def country_bin(x):
104     if x in europe:
105         return 'Europe'
106     elif x in north_a:
107         return 'North America'
108     elif x in south_a:
109         return 'South America'
110     elif x in asia:
111         return 'Asia'
112     elif x in africa:
113         return 'Africa'
114     elif x in australia:
115         return 'Australia'
116     elif x in Others:
117         return 'Others'
118     elif x in unk:
119         return 'Unknown'
120 df.country=df.country.apply(country_bin) 
121 
122 #所有国家分配成各个地区
123 df.country.unique()
124 
125 #酒店类型分布饼图
126 plt.rcParams['font.sans-serif'] = [u'SimHei']
127 plt.rcParams['axes.unicode_minus'] = False
128 plt.rcParams['figure.figsize']=[5,5]
129 plt.pie(df.hotel.value_counts().values,explode=[0,0.2],labels=df.hotel.value_counts().index,autopct='%.2f%%')
130 plt.title('酒店类型分布')
131 plt.show()
132 
133 #绘制酒店取消预订柱状图
134 pd.crosstab(df.hotel, df.is_canceled, values=df.is_canceled, aggfunc='count', normalize=True).plot.bar()
135 plt.title('酒店取消预订情况')
136 plt.ylabel('取消预订比例')
137 plt.xlabel('酒店类型')
138 plt.show()
139 
140 #绘制酒店取消预订数量表
141 tbl=pd.crosstab(df.hotel,df.is_canceled,margins=True)
142 tbl
143 
144 #添加一列 cancel_percent (取消预订的百分比)来显示取消的预订占总预订的百分比
145 tbl['cancel_percent']=tbl[1]*100/tbl['All']
146 tbl
147 
148 #绘制不同酒店类型的取消率
149 tbl.drop('All',axis=0)['cancel_percent'].plot.bar()
150 plt.title('不同酒店类型的取消率')
151 plt.xlabel('酒店类型')
152 plt.xticks(rotation=0)
153 plt.ylabel('取消数量百分比(%)')
154 plt.show()
155 
156 #通过 lead_time (入住前多长时间预订)列绘制直方图
157 sns.distplot(df.lead_time)
158 plt.show()
159 
160 #通过 is_canceled (是否取消预订)列和 lead_time (入住前多长时间预订)列绘制城市酒店的盒图
161 sns.boxplot(x='is_canceled',y='lead_time',data=df.loc[df.hotel=='City Hotel'])
162 plt.show()
163 
164 #通过 is_canceled (是否取消预订)列和 lead_time (入住前多长时间预订)列绘制假日酒店的盒图
165 sns.boxplot(x='is_canceled',y='lead_time',data=df.loc[df.hotel=='Resort Hotel'])
166 plt.show()
167 
168 #绘制两个酒店每年预订的柱状图
169 plt.rcParams['figure.figsize']=[8,5]
170 sns.countplot(x='arrival_date_year',data=df,hue='hotel')
171 plt.xlabel('年份')
172 plt.ylabel('预订数量')
173 plt.title('每年的预订')
174 plt.show()
175 
176 # 显示全年取消率的表
177 tbl=pd.crosstab(df.arrival_date_year,df.is_canceled,margins=True)
178 tbl
179 
180 #添加一列 cancel-percent (取消预订的百分比)来显示取消的预订占总预订的百分比
181 tbl['cancel-percent']=tbl[1]*100/tbl['All']
182 tbl
183 
184 #绘制全年取消率柱状图
185 tbl.drop('All',axis=0)['cancel-percent'].plot.bar()
186 plt.xticks(rotation=0)
187 plt.xlabel('年份')
188 plt.ylabel('取消数量百分比(%)')
189 plt.title('2015-2017年取消率')
190 plt.show()
191 
192 #绘制每个年份的取消预订的数量所占所有取消预订的总数的比例。
193 df[df.is_canceled==1]['arrival_date_year'].value_counts()/len(df[df.is_canceled==1])
194 
195 #绘制每月的预订数量
196 plt.rcParams['figure.figsize']=[8,5]
197 sns.countplot(x='arrival_date_month',data=df,order=df.arrival_date_month.value_counts().index)
198 plt.title('每月预订数量 ')
199 plt.xlabel('预订月份')
200 plt.ylabel('预订数量')
201 plt.xticks(rotation=60,ha='right')
202 plt.show()
203 
204 #绘制每月预订数量
205 plt.rcParams['figure.figsize']=[8,5]
206 sns.countplot(x='arrival_date_month',data=df,order=df.arrival_date_month.value_counts().index,hue='hotel')
207 plt.title('每月预订数量 ')
208 plt.xlabel('Booking Month')
209 plt.ylabel('Number of Bookings')
210 plt.xticks(rotation=60,ha='right')
211 plt.show()
212 
213 #显示每个月预订数量
214 tbl=pd.crosstab(df.arrival_date_month,df.is_canceled,margins=True)
215 tbl
216 
217 #添加一列 cancel-percent (取消预订的百分比)来显示取消的预订占总预订的百分比
218 tbl['cancel_percent']=tbl[1]*100/tbl['All']
219 tbl
220 
221 #将上表中的取消预订的百分比进行绘制
222 tbl.drop('All',axis=0)['cancel_percent'].plot.bar()
223 plt.title('每个月取消预订百分比')
224 plt.xlabel('月份')
225 plt.ylabel('取消预订百分比(%)')
226 plt.show()
227 
228 #绘制第几周入住的柱状图
229 plt.figure(figsize=(10,15))
230 sns.countplot(x='arrival_date_week_number',data=df)
231 plt.title('每周入住数量')
232 plt.xticks(rotation='vertical')
233 plt.xlabel('每年的周数')
234 plt.ylabel('数量')
235 plt.show()
236 
237 #绘制周末入住持续天数
238 plt.figure(figsize=(7,7))
239 sns.distplot(df.stays_in_weekend_nights)
240 plt.title('周末入住持续天数')
241 plt.xlabel('周末入住天数')
242 plt.ylabel('密度')
243 plt.show()
244 
245 #通过 hotel (酒店)列和stays_in_weekend_nights(周末入住天数)列绘制盒图
246 plt.figure(figsize=(7,7))
247 sns.boxplot(x='hotel',y='stays_in_weekend_nights',data=df)
248 plt.show()
249 
250 #绘制成年人预定人数入住图
251 plt.figure(figsize=(5,5))
252 sns.distplot(df.loc[(df.stays_in_week_nights==0) & (df.stays_in_weekend_nights==0)]['adults'])
253 plt.title('成年人预订人数图')
254 plt.ylabel('密度')
255 plt.xlabel('成年人预订人数')
256 plt.show()
257 
258 #绘制婴儿预订入住图
259 plt.figure(figsize=(5,5))
260 sns.distplot(df.babies)
261 plt.title('婴儿预订入住图')
262 plt.ylabel('密度')
263 plt.xlabel('婴儿数量')
264 plt.show()
265 
266 #绘制国家地区频率分布图
267 plt.figure(figsize=(8,8))
268 sns.countplot(x='country',data=df)
269 plt.title('国家地区频率分布')
270 plt.xticks(rotation=60,ha='right')
271 plt.ylabel('数量')
272 plt.xlabel('国家地区')
273 plt.show()
274 
275 #生成国家地区是否取消预订表
276 tbl=pd.crosstab(df.country,df.is_canceled,margins=True)
277 tbl
278 
279 #添加一列 cancel-percent (取消预订的百分比)来显示取消的预订占总预订的百分比
280 tbl['cancel_percent']=tbl[1]*100/tbl['All']
281 tbl
282 
283 #绘制国家地区取消预订百分比图
284 plt.figure(figsize=(7,7))
285 tbl.drop('All',axis=0)['cancel_percent'].plot.bar()
286 plt.title('国家地区取消预订百分比图')
287 plt.xticks(rotation=60,ha='right')
288 plt.ylabel('取消预订百分比(%)')
289 plt.xlabel('国家地区')
290 plt.show()
291 
292 #绘制市场划分图
293 plt.rcParams['figure.figsize']=[7,7]
294 sns.countplot(x='market_segment',data=df)
295 plt.xticks(rotation=60,ha='right')
296 plt.title('市场划分图')
297 plt.ylabel('数量')
298 plt.xlabel('市场划分')
299 plt.show()
300 
301 #显示市场划分数量表
302 tbl=pd.crosstab(df.market_segment,df.is_canceled,margins=True)
303 tbl
304 
305 #添加一列 cancel-percent (取消预订的百分比)来显示取消的预订占总预订的百分比
306 tbl['cancel_percent']=tbl[1]*100/tbl['All']
307 tbl
308 
309 #绘制市场取消率图
310 tbl.drop('All',axis=0)['cancel_percent'].plot.bar()
311 plt.title('市场取消率')
312 plt.xticks(rotation=60,ha='right')
313 plt.ylabel('取消预订百分比(%)')
314 plt.xlabel('市场划分')
315 plt.show()
316 
317 #绘制市场分布渠道图
318 sns.countplot(x='distribution_channel',data=df)
319 plt.title('市场分布渠道图')
320 plt.ylabel('数量')
321 plt.xlabel('市场分布渠道')
322 plt.show()
323 
324 #显示市场分布渠道数量表
325 tbl=pd.crosstab(df.distribution_channel,df.is_canceled,margins=True)
326 tbl
327 
328 ##添加一列 cancel-percent (取消预订的百分比)来显示取消的预订占总预订的百分比
329 tbl['cancel_percent']=tbl[1]*100/tbl['All']
330 tbl
331 
332 #绘制市场分布渠道百分比图
333 tbl.drop('All',axis=0)['cancel_percent'].plot.bar()
334 plt.title('市场分布渠道百分比图')
335 plt.ylabel('取消预订百分比(%)')
336 plt.xlabel('分布渠道')
337 plt.show()

 

四、 总结

 1、结论

  通过大数据分析,发现城市酒店的预定量比假日酒店的预定量多。可能是因为城市酒店位置优越,方便前往商务场所或者旅游景点。此外,城市酒店的价格可能比假日酒店的价格更容易接受。然而,城市酒店的预订取消率可能比假日酒店的高,可能是因为城市酒店的客户群更为多样化,其中可能包括许多商务旅客。这些商务旅客可能会因为工作原因或其他突发事件而不得不取消预订。而且,城市酒店的客户群还可能包括许多自由行旅客,这些旅客可能会因为个人原因而取消预订。相比之下,假日酒店的客户群可能更加稳定,因为假日酒店通常是为度假或休闲而安排的,因此客户可能不太可能因为工作或其他突发事件而取消预订。

  根据国家地区的分析,酒店具有较多的欧盟客户,说明此数据集是来自于欧盟的酒店数据。这也说明了欧盟国家之间的贸易和经济联系较为紧密,欧盟的人们也更愿意前往邻国旅游。除欧盟本地外,还有不少其他国家和地区的客户,这可能是因为欧盟国家在旅游业方面具有较高的吸引力,包括丰富的文化、历史和自然风光。此外,欧盟国家的交通和通信设施也可能较为发达,使得前往这些国家旅游更加方便。根据分析还发现,酒店的客户中,北美洲的客户取消率普遍偏低而非洲的取消率较高,这说明了北美国家的经济和稳定性较高,因此可能会有较少的突发事件导致客户取消预订,另一方面,非洲国家可能存在较多的政治、经济和社会不稳定因素,这可能会导致客户更容易取消预订。例如,非洲国家可能存在较多的冲突和动乱,这可能会使客户担心前往这些国家的安全。此外,非洲国家的经济可能不太稳定,这也可能会使客户担心旅行的费用是否会发生变化。

  在酒店的市场分布分析中发现,旅行社的数量较高,同时取消率也是最高的,而公司的取消率是最低,这说明了,在旅行酒店住宿方面,旅行社承担了大量的旅行组织和安排工作,并且需要在较短的时间内安排较多的旅行。因此,旅行社可能会受到更多的压力,以确保所有的旅行安排都能顺利进行。另一方面,公司的数量可能较少,但是取消率可能较低。这可能是因为公司旅行通常是为了公司的业务目的而安排的,因此取消的风险可能较小。公司旅行还可能会有更多的提前安排和计划,这可能会使取消的风险更小。

 

2、收获

  在这次设计过程中让我更加了解了什么是数据,了解了数据之间的关系,并让我更加熟悉了,pandas库、seaborn库、pyplot等方法的使用。这些可以帮助我对未来的趋势和变化进行预测,让我可以更好的了解市场与客户,可以通过大数据分析来提高业绩,这可以为我带来更多的竞争优势。

  在这次的设计过程中,需要修改进步的地方还有很多,比如,可以更改绘图功能,也就是优化数据可视化工具,以便更好的呈现数据。如果可能,可以考虑引入机器学习,以提高效率。