Main Catalogue
Introduction
1.1 Introduction that explains the problem statement we are addressing
In the hospitality and lodging industry, determining the optimal nightly room rate—known as the Average Daily Rate (adr)—is a critical challenge that dictates a business’s survival and profitability. However, the tourism market is complex and volatile, influenced simultaneously by a multitude of factors: ranging from seasonality (arrival_date_month) and booking lead time (lead_time) to guest group size and composition (adults, children), market segment (market_segment), and additional service requirements (meal, required_car_parking_spaces, total_of_special_requests). Without a clear understanding of the quantitative relationships between these variables and room rates, hotel managers often face two risky scenarios: setting rates too high, resulting in low occupancy, or setting them too low, leading to a loss of potential revenue. Consequently, this study aims to develop a regression analysis model to accurately forecast the ADR while simultaneously isolating the impact of each individual factor on room rates.
1.2 Short explanation of how we plan to address this problem statement
Our team is using the “Hotels” dataset obtained from GitHub. We will perform preprocessing steps to clean the data, including handling missing values and outliers. Additionally, we will create visualizations (such as ggplot charts, histograms, and other plots) and process the data to analyze key information. The data will be visualized to identify groups of factors influencing the Average Daily Rate (adr) variable, specifically: the Timing group (lead_time, arrival_date_month, arrival_date_week_number, stays_in_weekend_nights, stays_in_week_nights), the Customer Characteristics group (adults, children, customer_type, market_segment), and the Services group (meal, required_car_parking_spaces, total_of_special_requests).1.3 About current proposed approach/analytic technique we think will address this problem.
Regression analysis allows us to explore the relationship between each variable and the Average Daily Rate (adr), thereby identifying which group of factors has the strongest impact.## 1.4 Explain how your analysis will help the consumer of your analysis.
First, for revenue managers and optimization specialists, this study provides a scientific basis for transitioning from intuition-based pricing to data-driven dynamic pricing strategies. Understanding the quantitative impact of specific factors enables businesses to proactively adjust prices in real time, thereby optimizing revenue and enhancing their competitive advantage. Second, the research findings not only address financial objectives but also assist operations teams in optimizing the customer experience by developing personalized service packages and pricing tailored to specific market segments.Packages Required
2.1 All packages used are loaded upfront so the reader knows which are required to replicate the analysis.
library(tidyverse)
library(dplyr)
library(tidyr)
library(ggplot2)
library(lubridate)
library(knitr)
library(kableExtra)
library(feasts)
library(here)
library(janitor)
library(glue)
library(tsibble)
library(fabletools)
2.2 Messages and warnings resulting from loading the package are suppressed.
2.3 Explanation is regarding the purpose of each package
- library(tidyverse): Supports the entire workflow of data processing, analysis, and visualization.
- library(dplyr): Provides powerful functions for data manipulation and transformation.
- library(tidyr): Helps clean and restructure data into a tidy format.
- library(ggplot2): A graphics library based on the “Grammar of Graphics,” used to create professional, customizable charts and graphs.
- library(lubridate): Used to easily process and manipulate date and time data.
- library(knitr): Supports dynamic report generation, particularly by compiling R Markdown files into HTML, PDF, or Word formats.
- library(kableExtra): Helps customize, format, and style tables for visually appealing HTML/PDF reports.
- library(feasts): Provides tools for time series data analysis.
- library(here): Manages relative file paths within the project root, ensuring code runs consistently across different computers.
- library(janitor): Assists in cleaning raw data, standardizing column names, and quickly generating frequency tables.
- library(glue): Used to embed variables and expressions directly into text strings cleanly and efficiently.
- library(tsibble): Provides a tabular data structure specifically for time series (time series data frame), enabling flexible time-based data handling.
- library(fabletools): Provides core tools and infrastructure for time series analysis, evaluation, and forecasting.
Data Preparation
3.1 Original source where the data was obtained is cited and, if possible, hyperlinked.
Our team uses the hotel booking demand dataset by Antonio, Almeida, and Nunes (2019), which is publicly available on GitHub Link dataset: Hotels
3.2 Source data is thoroughly explained
- Source: an open hotel booking demand dataset from Antonio, Almeida and Nunes, 2019.
- Purpose: Used for time-series analysis and time-series forecasting of hotel booking data.
- Date Created: TidyTuesday dataset release date is 2020-02-11
- Number of variables: The dataset contains 32 variables.
- Authors: Nuno Antonio, Ana de Almeida, and Luis Nunes (2019)
- Missing Values:The dataset contains missing values (NA) in columns such as children, country, agent, and company.
3.3. Data importing and cleaning steps are explained in the text
- First, we will import the data for analysis and examine its general characteristics.
- Next, we will proceed with data cleaning according to the following steps: Step 1: Remove variables not used in the analysis to avoid confusion. Step 2: Convert data types for certain variables to facilitate the research process. Step 3: Assess and remove missing values to ensure a clean dataset and accurate analysis results. Step 4: Handle outliers to prevent them from skewing the analysis results. Step 5: Present the structure of the resulting dataset.
- Finally, we will re-examine the general characteristics of the data and conduct a preliminary analysis.
3.3.1. Import the data set into Rstudio:
hotel <- read.csv("C:/Users/miam/Desktop/X Fall Semester/Data Wrangling/Midterm Project/hotels/hotels.csv")
3.3.2. View structure of the data set:
str(hotel)
## 'data.frame': 119390 obs. of 32 variables:
## $ hotel : chr "Resort Hotel" "Resort Hotel" "Resort Hotel" "Resort Hotel" ...
## $ is_canceled : int 0 0 0 0 0 0 0 0 1 1 ...
## $ lead_time : int 342 737 7 13 14 14 0 9 85 75 ...
## $ arrival_date_year : int 2015 2015 2015 2015 2015 2015 2015 2015 2015 2015 ...
## $ arrival_date_month : chr "July" "July" "July" "July" ...
## $ arrival_date_week_number : int 27 27 27 27 27 27 27 27 27 27 ...
## $ arrival_date_day_of_month : int 1 1 1 1 1 1 1 1 1 1 ...
## $ stays_in_weekend_nights : int 0 0 0 0 0 0 0 0 0 0 ...
## $ stays_in_week_nights : int 0 0 1 1 2 2 2 2 3 3 ...
## $ adults : int 2 2 1 1 2 2 2 2 2 2 ...
## $ children : int 0 0 0 0 0 0 0 0 0 0 ...
## $ babies : int 0 0 0 0 0 0 0 0 0 0 ...
## $ meal : chr "BB" "BB" "BB" "BB" ...
## $ country : chr "PRT" "PRT" "GBR" "GBR" ...
## $ market_segment : chr "Direct" "Direct" "Direct" "Corporate" ...
## $ distribution_channel : chr "Direct" "Direct" "Direct" "Corporate" ...
## $ is_repeated_guest : int 0 0 0 0 0 0 0 0 0 0 ...
## $ previous_cancellations : int 0 0 0 0 0 0 0 0 0 0 ...
## $ previous_bookings_not_canceled: int 0 0 0 0 0 0 0 0 0 0 ...
## $ reserved_room_type : chr "C" "C" "A" "A" ...
## $ assigned_room_type : chr "C" "C" "C" "A" ...
## $ booking_changes : int 3 4 0 0 0 0 0 0 0 0 ...
## $ deposit_type : chr "No Deposit" "No Deposit" "No Deposit" "No Deposit" ...
## $ agent : chr "NULL" "NULL" "NULL" "304" ...
## $ company : chr "NULL" "NULL" "NULL" "NULL" ...
## $ days_in_waiting_list : int 0 0 0 0 0 0 0 0 0 0 ...
## $ customer_type : chr "Transient" "Transient" "Transient" "Transient" ...
## $ adr : num 0 0 75 75 98 ...
## $ required_car_parking_spaces : int 0 0 0 0 0 0 0 0 0 0 ...
## $ total_of_special_requests : int 0 0 0 0 1 1 0 1 1 0 ...
## $ reservation_status : chr "Check-Out" "Check-Out" "Check-Out" "Check-Out" ...
## $ reservation_status_date : chr "2015-07-01" "2015-07-01" "2015-07-02" "2015-07-02" ...
3.3.3. View summary statistics of the data set:
summary(hotel)
## hotel is_canceled lead_time arrival_date_year
## Length :119390 Min. :0.0000 Min. : 0 Min. :2015
## N.unique : 2 1st Qu.:0.0000 1st Qu.: 18 1st Qu.:2016
## N.blank : 0 Median :0.0000 Median : 69 Median :2016
## Min.nchar: 10 Mean :0.3704 Mean :104 Mean :2016
## Max.nchar: 12 3rd Qu.:1.0000 3rd Qu.:160 3rd Qu.:2017
## Max. :1.0000 Max. :737 Max. :2017
##
## arrival_date_month arrival_date_week_number arrival_date_day_of_month
## Length :119390 Min. : 1.00 Min. : 1.0
## N.unique : 12 1st Qu.:16.00 1st Qu.: 8.0
## N.blank : 0 Median :28.00 Median :16.0
## Min.nchar: 3 Mean :27.17 Mean :15.8
## Max.nchar: 9 3rd Qu.:38.00 3rd Qu.:23.0
## Max. :53.00 Max. :31.0
##
## stays_in_weekend_nights stays_in_week_nights adults
## Min. : 0.0000 Min. : 0.0 Min. : 0.000
## 1st Qu.: 0.0000 1st Qu.: 1.0 1st Qu.: 2.000
## Median : 1.0000 Median : 2.0 Median : 2.000
## Mean : 0.9276 Mean : 2.5 Mean : 1.856
## 3rd Qu.: 2.0000 3rd Qu.: 3.0 3rd Qu.: 2.000
## Max. :19.0000 Max. :50.0 Max. :55.000
##
## children babies meal country
## Min. : 0.0000 Min. : 0.000000 Length :119390 Length :119390
## 1st Qu.: 0.0000 1st Qu.: 0.000000 N.unique : 5 N.unique : 178
## Median : 0.0000 Median : 0.000000 N.blank : 0 N.blank : 0
## Mean : 0.1039 Mean : 0.007949 Min.nchar: 2 Min.nchar: 2
## 3rd Qu.: 0.0000 3rd Qu.: 0.000000 Max.nchar: 9 Max.nchar: 4
## Max. :10.0000 Max. :10.000000
## NAs :4
## market_segment distribution_channel is_repeated_guest
## Length :119390 Length :119390 Min. :0.00000
## N.unique : 8 N.unique : 5 1st Qu.:0.00000
## N.blank : 0 N.blank : 0 Median :0.00000
## Min.nchar: 6 Min.nchar: 3 Mean :0.03191
## Max.nchar: 13 Max.nchar: 9 3rd Qu.:0.00000
## Max. :1.00000
##
## previous_cancellations previous_bookings_not_canceled reserved_room_type
## Min. : 0.00000 Min. : 0.0000 Length :119390
## 1st Qu.: 0.00000 1st Qu.: 0.0000 N.unique : 10
## Median : 0.00000 Median : 0.0000 N.blank : 0
## Mean : 0.08712 Mean : 0.1371 Min.nchar: 1
## 3rd Qu.: 0.00000 3rd Qu.: 0.0000 Max.nchar: 1
## Max. :26.00000 Max. :72.0000
##
## assigned_room_type booking_changes deposit_type agent
## Length :119390 Min. : 0.0000 Length :119390 Length :119390
## N.unique : 12 1st Qu.: 0.0000 N.unique : 3 N.unique : 334
## N.blank : 0 Median : 0.0000 N.blank : 0 N.blank : 0
## Min.nchar: 1 Mean : 0.2211 Min.nchar: 10 Min.nchar: 1
## Max.nchar: 1 3rd Qu.: 0.0000 Max.nchar: 10 Max.nchar: 4
## Max. :21.0000
##
## company days_in_waiting_list customer_type adr
## Length :119390 Min. : 0.000 Length :119390 Min. : -6.38
## N.unique : 353 1st Qu.: 0.000 N.unique : 4 1st Qu.: 69.29
## N.blank : 0 Median : 0.000 N.blank : 0 Median : 94.58
## Min.nchar: 1 Mean : 2.321 Min.nchar: 5 Mean : 101.83
## Max.nchar: 4 3rd Qu.: 0.000 Max.nchar: 15 3rd Qu.: 126.00
## Max. :391.000 Max. :5400.00
##
## required_car_parking_spaces total_of_special_requests reservation_status
## Min. :0.00000 Min. :0.0000 Length :119390
## 1st Qu.:0.00000 1st Qu.:0.0000 N.unique : 3
## Median :0.00000 Median :0.0000 N.blank : 0
## Mean :0.06252 Mean :0.5714 Min.nchar: 7
## 3rd Qu.:0.00000 3rd Qu.:1.0000 Max.nchar: 9
## Max. :8.00000 Max. :5.0000
##
## reservation_status_date
## Length :119390
## N.unique : 926
## N.blank : 0
## Min.nchar: 10
## Max.nchar: 10
##
##
3.3.4. Deleted Unused Variables:
Variables not used in the analysis will be removed to avoid confusion:
Variables related to booking status such as
is_canceled,reservation_status, andreservation_status_datepertain to the task of cancellation prediction rather than room pricing.arrival_date_week_numberwas removed because our group chose to analyze by month (arrival_date_month), season (season), and booking lead time (lead_time_category), which could lead to overlapping week-of-the-year data.Customer history variables such as
previous_cancellations,previous_bookings_not_canceled, andis_repeated_guestwere also excluded to focus entirely on optimizing pricing strategies based on the current timing and segment.Variables such as
country,agent, andcompanyhave too many discrete values, making the model overly complex.distribution channelwas deleted because its meaning overlapped withmarket_segment.The
days_in_waiting_listvariable reflects a hotel’s popularity or occupancy status, but it is not a direct determinant of the rate a customer pays (adr) at the time of booking.
hotel$hotel <- NULL
hotel$is_canceled <- NULL
hotel$arrival_date_week_number <- NULL
hotel$country <- NULL
hotel$distribution_channel <- NULL
hotel$is_repeated_guest <- NULL
hotel$previous_cancellations <- NULL
hotel$previous_bookings_not_canceled <- NULL
hotel$assigned_room_type <- NULL
hotel$booking_changes <- NULL
hotel$deposit_type <- NULL
hotel$agent <- NULL
hotel$company <- NULL
hotel$days_in_waiting_list <- NULL
hotel$reservation_status <- NULL
hotel$reservation_status_date <- NULL
3.3.5. Handle missing values
Count missing values
colSums(is.na(hotel))
## lead_time arrival_date_year
## 0 0
## arrival_date_month arrival_date_day_of_month
## 0 0
## stays_in_weekend_nights stays_in_week_nights
## 0 0
## adults children
## 0 4
## babies meal
## 0 0
## market_segment reserved_room_type
## 0 0
## customer_type adr
## 0 0
## required_car_parking_spaces total_of_special_requests
## 0 0
There are 4 missing values come from variable
children
Discard missing values
hotel <- na.omit(hotel)
3.3.6. Conversion format
We want to convert these variables into factors to facilitate data processing and avoid errors when generating chartshotels_conversion <- hotel %>%
mutate(
reserved_room_type = as.factor(reserved_room_type),
customer_type = as.factor(customer_type),
market_segment = as.factor(market_segment),
meal = as.factor(meal),
arrival_date_month = as.factor(arrival_date_month))
3.3.7. Create new dimensions
We will create two new variables to provide additional perspectives
for the analysis: * Season: It helps assess how the Average
Daily Rate (adr) varies based on the timeframes in which
guests book their rooms.
Lead_time_category: Facilitates the analysis of seasonality, providing a clear view of room rate fluctuations throughout the year to support dynamic pricing strategies.
hotels_new <- hotels_conversion %>%
mutate(
lead_time_category = case_when(
lead_time <= 7 ~ "Last_minute",
lead_time <= 30 ~ "Short_term",
TRUE ~ "Long_term"),
season = case_when(
arrival_date_month %in% c("December", "January", "February") ~ "Winter",
arrival_date_month %in% c("March", "April", "May") ~ "Spring",
arrival_date_month %in% c("June", "July", "August") ~ "Summer",
arrival_date_month %in% c("September", "October", "November") ~ "Autumn"
) )
3.3.8. Handle outlier
Finding outlier
boxplot(hotels_new$adr)
Discard outlier
To eliminate excessively high or low values, we apply thresholds of 1.5 × IQR above the third quartile and 1.5 × IQR below the first quartile to identify and remove outliers. Q1 <- quantile(hotels_new$adr, 0.25, na.rm = TRUE)
Q3 <- quantile(hotels_new$adr, 0.75, na.rm = TRUE)
IQR <- Q3 - Q1
upper_bound <- Q3 + 1.5 * IQR
lower_bound <- Q1 - 1.5 * IQR
hotels_clean <- hotels_new %>%
filter(adr >= lower_bound & adr <= upper_bound)
Double check outlier
boxplot(hotels_clean$adr)
3.4. The final data set looks like.
kableExtra::scroll_box(
kableExtra::kable_paper(
kableExtra::kbl(head(hotels_clean, 10))
),
width = "800px",
height = "500px"
)
| lead_time | arrival_date_year | arrival_date_month | arrival_date_day_of_month | stays_in_weekend_nights | stays_in_week_nights | adults | children | babies | meal | market_segment | reserved_room_type | customer_type | adr | required_car_parking_spaces | total_of_special_requests | lead_time_category | season |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 342 | 2015 | July | 1 | 0 | 0 | 2 | 0 | 0 | BB | Direct | C | Transient | 0.0 | 0 | 0 | Long_term | Summer |
| 737 | 2015 | July | 1 | 0 | 0 | 2 | 0 | 0 | BB | Direct | C | Transient | 0.0 | 0 | 0 | Long_term | Summer |
| 7 | 2015 | July | 1 | 0 | 1 | 1 | 0 | 0 | BB | Direct | A | Transient | 75.0 | 0 | 0 | Last_minute | Summer |
| 13 | 2015 | July | 1 | 0 | 1 | 1 | 0 | 0 | BB | Corporate | A | Transient | 75.0 | 0 | 0 | Short_term | Summer |
| 14 | 2015 | July | 1 | 0 | 2 | 2 | 0 | 0 | BB | Online TA | A | Transient | 98.0 | 0 | 1 | Short_term | Summer |
| 14 | 2015 | July | 1 | 0 | 2 | 2 | 0 | 0 | BB | Online TA | A | Transient | 98.0 | 0 | 1 | Short_term | Summer |
| 0 | 2015 | July | 1 | 0 | 2 | 2 | 0 | 0 | BB | Direct | C | Transient | 107.0 | 0 | 0 | Last_minute | Summer |
| 9 | 2015 | July | 1 | 0 | 2 | 2 | 0 | 0 | FB | Direct | C | Transient | 103.0 | 0 | 1 | Short_term | Summer |
| 85 | 2015 | July | 1 | 0 | 3 | 2 | 0 | 0 | BB | Online TA | A | Transient | 82.0 | 0 | 1 | Long_term | Summer |
| 75 | 2015 | July | 1 | 0 | 3 | 2 | 0 | 0 | HB | Offline TA/TO | D | Transient | 105.5 | 0 | 0 | Long_term | Summer |
3.5 Summary information about the variables of concern in your cleaned data set.
General information about the variables
str(hotels_clean)
## 'data.frame': 115593 obs. of 18 variables:
## $ lead_time : int 342 737 7 13 14 14 0 9 85 75 ...
## $ arrival_date_year : int 2015 2015 2015 2015 2015 2015 2015 2015 2015 2015 ...
## $ arrival_date_month : Factor w/ 12 levels "April","August",..: 6 6 6 6 6 6 6 6 6 6 ...
## $ arrival_date_day_of_month : int 1 1 1 1 1 1 1 1 1 1 ...
## $ stays_in_weekend_nights : int 0 0 0 0 0 0 0 0 0 0 ...
## $ stays_in_week_nights : int 0 0 1 1 2 2 2 2 3 3 ...
## $ adults : int 2 2 1 1 2 2 2 2 2 2 ...
## $ children : int 0 0 0 0 0 0 0 0 0 0 ...
## $ babies : int 0 0 0 0 0 0 0 0 0 0 ...
## $ meal : Factor w/ 5 levels "BB","FB","HB",..: 1 1 1 1 1 1 1 2 1 3 ...
## $ market_segment : Factor w/ 7 levels "Aviation","Complementary",..: 4 4 4 3 7 7 4 4 7 6 ...
## $ reserved_room_type : Factor w/ 10 levels "A","B","C","D",..: 3 3 1 1 1 1 3 3 1 4 ...
## $ customer_type : Factor w/ 4 levels "Contract","Group",..: 3 3 3 3 3 3 3 3 3 3 ...
## $ adr : num 0 0 75 75 98 ...
## $ required_car_parking_spaces: int 0 0 0 0 0 0 0 0 0 0 ...
## $ total_of_special_requests : int 0 0 0 0 1 1 0 1 1 0 ...
## $ lead_time_category : chr "Long_term" "Long_term" "Last_minute" "Short_term" ...
## $ season : chr "Summer" "Summer" "Summer" "Summer" ...
## - attr(*, "na.action")= 'omit' Named int [1:4] 40601 40668 40680 41161
## ..- attr(*, "names")= chr [1:4] "40601" "40668" "40680" "41161"
summary(hotels_clean)
## lead_time arrival_date_year arrival_date_month arrival_date_day_of_month
## Min. : 0 Min. :2015 August :11967 Min. : 1.00
## 1st Qu.: 18 1st Qu.:2016 July :11780 1st Qu.: 8.00
## Median : 70 Median :2016 May :11571 Median :16.00
## Mean :105 Mean :2016 October:11100 Mean :15.77
## 3rd Qu.:162 3rd Qu.:2017 April :10937 3rd Qu.:23.00
## Max. :737 Max. :2017 June :10696 Max. :31.00
## (Other):47542
## stays_in_weekend_nights stays_in_week_nights adults
## Min. : 0.0000 Min. : 0.000 Min. : 0.000
## 1st Qu.: 0.0000 1st Qu.: 1.000 1st Qu.: 2.000
## Median : 1.0000 Median : 2.000 Median : 2.000
## Mean : 0.9208 Mean : 2.481 Mean : 1.846
## 3rd Qu.: 2.0000 3rd Qu.: 3.000 3rd Qu.: 2.000
## Max. :19.0000 Max. :50.000 Max. :55.000
##
## children babies meal market_segment
## Min. : 0.00000 Min. : 0.000000 BB :89932 Aviation : 237
## 1st Qu.: 0.00000 1st Qu.: 0.000000 FB : 718 Complementary: 743
## Median : 0.00000 Median : 0.000000 HB :13189 Corporate : 5289
## Mean : 0.08268 Mean : 0.007492 SC :10649 Direct :11716
## 3rd Qu.: 0.00000 3rd Qu.: 0.000000 Undefined: 1105 Groups :19712
## Max. :10.00000 Max. :10.000000 Offline TA/TO:24111
## Online TA :53785
## reserved_room_type customer_type adr
## A :85361 Contract : 4062 Min. : -6.38
## D :18522 Group : 564 1st Qu.: 68.00
## E : 5933 Transient :86132 Median : 92.00
## F : 2205 Transient-Party:24835 Mean : 97.04
## G : 1366 3rd Qu.:121.37
## B : 1102 Max. :211.03
## (Other): 1104
## required_car_parking_spaces total_of_special_requests lead_time_category
## Min. :0.00000 Min. :0.0000 Length :115593
## 1st Qu.:0.00000 1st Qu.:0.0000 N.unique : 3
## Median :0.00000 Median :0.0000 N.blank : 0
## Mean :0.05967 Mean :0.5617 Min.nchar: 9
## 3rd Qu.:0.00000 3rd Qu.:1.0000 Max.nchar: 11
## Max. :8.00000 Max. :5.0000
##
## season
## Length :115593
## N.unique : 4
## N.blank : 0
## Min.nchar: 6
## Max.nchar: 6
##
##
Guest Profile & Length of Stay: Bookings primarily consist of adults (averaging 1.85 adults per booking), with fewer children and infants. The average length of stay is approximately 0.92 weekend nights and 2.48 weekday nights.
Average Daily Rate (
adr): The mean value is 97.04 and the median is 92.00, with prices ranging from a minimum of -6.38 to a maximum of 211.03.Meal: The Bed & Breakfast (BB) option is the most popular choice by a wide margin (89,932 bookings).Market_segment: Online Travel Agencies (OTAs) account for the largest booking channel, with 53,785 records.Reserved_room_type: Room Type A is the most frequently reserved room type, with 85,361 bookings.customer_type: The majority of customers are classified as “Transient,” with 86,132 records.
3.6. Some preliminary analyses
We conducted a preliminary analysis of the “Seasonal Fluctuations in Average Daily Rate” chart to determine how rates vary by season and to identify which market segments are currently priced high. hotels_clean %>%
group_by(season, market_segment) %>%
summarise(avg_adr = mean(adr, na.rm = TRUE), .groups = "drop") %>%
ggplot(aes(x = season, y = avg_adr, color = market_segment, group = market_segment)) +
geom_line(linewidth = 1) +
geom_point(size = 2) +
labs(
title = "Seasonal Fluctuations in Average Daily Rate (ADR)",
x = "Season",
y = "Average ADR",
color = "Market Segment"
) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
Proposed Exploratory Data Analysis
4.1 Discuss how you plan to uncover new information in the data that is not self-evident. What are different ways you could look at this data to answer the questions you want to answer? Do you plan to slice and dice the data in different ways, create new variables, or join separate data frames to create new summary information? How could you summarize your data to answer key questions?
Does the lead time significantly impact the room rate (ADR), and do early bookers pay more or less than last-minute bookers?
How do timing factors (seasonality, arrival month, and weekend vs. weeknight stays) influence dynamic pricing variations?
Do customer and room characteristics (number of adults/children, reserved room type, market segment, and customer type) strongly correlate with higher ADR?
Does requesting additional services (meal plans, parking spaces, or special requests) result in a statistically significant increase in the room rate?
Which customer segments or market channels generate the highest ADR across different seasons?
Does the price sensitivity of different market segments vary across lead-time categories?
How does the combined interaction of seasonality and customer special requests influence overall ADR optimization?
4.2 What types of plots and tables will help you to illustrate the findings to your questions?
Scatter Plot with Trend line: To examine the continuous relationship between booking lead time (
lead_time_category) and room rate (adr), helping to determine whether guests who book in advance or those who book at the last minute secure better rates.Line Charts: Used to track trends in average ADR across months (arrival_date_month) and seasons, thereby visualizing dynamic pricing patterns between peak and off-peak periods.
Box plot: To illustrate the distribution, median value, and dispersion of ADR based on qualitative customer and room attributes, such as reserved room type (reserved_room_type), market segment (market_segment), and customer type (customer_type).
Grouped Bar Charts: To compare average ADR based on length of stay (weekend nights vs. weekday nights) and guest composition (adults, children, and babies).
Scatter plot: to analyze the impact of additional service options (meal, required_car_parking_spaces, and total_of_special_requests) on ADR (
adr)Regression Output Tables: These present model coefficients and standard errors, thereby demonstrating the statistical significance and magnitude of the impact of variable on ADR.
4.3 What do you not know how to do right now that you need to learn to answer your questions?
Understand how to draw scatter plots and heat maps in R to better visualize the data
How to perform linear regression analysis on R
Using discriminant analysis, cluster analysis
4.4 Do you plan on incorporating any machine learning techniques (i.e. linear regression, discriminant analysis, cluster analysis) to answer your questions?
We will use multiple linear regression to model the relationship between our target variable (adr) and various independent predictors, including timing factors (lead_time, season), customer and room characteristics (reserved_room_type, market_segment), and services (meal, total_of_special_requests). This will help us quantify the exact impact and statistical significance of each driver on room pricing.
We plan to use clustering techniques (such as k-means or hierarchical clustering) to group bookings or customers based on similarities in their behavior—such as lead time, length of stay, and service demands. This will help uncover hidden customer segments that are not immediately self-evident, directly supporting a more tailored dynamic pricing strategy.