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, and reservation_status_datepertain to the task of cancellation prediction rather than room pricing.

  • arrival_date_week_number was 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, and is_repeated_guestwere also excluded to focus entirely on optimizing pricing strategies based on the current timing and segment.

  • Variables such as country, agent, and company have too many discrete values, making the model overly complex.

  • distribution channel was deleted because its meaning overlapped with market_segment.

  • The days_in_waiting_list variable 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 charts
hotels_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?

  1. Does the lead time significantly impact the room rate (ADR), and do early bookers pay more or less than last-minute bookers?

  2. How do timing factors (seasonality, arrival month, and weekend vs. weeknight stays) influence dynamic pricing variations?

  3. Do customer and room characteristics (number of adults/children, reserved room type, market segment, and customer type) strongly correlate with higher ADR?

  4. Does requesting additional services (meal plans, parking spaces, or special requests) result in a statistically significant increase in the room rate?

  5. Which customer segments or market channels generate the highest ADR across different seasons?

  6. Does the price sensitivity of different market segments vary across lead-time categories?

  7. 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?

  1. 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.

  2. 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.

  3. 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).

  4. Grouped Bar Charts: To compare average ADR based on length of stay (weekend nights vs. weekday nights) and guest composition (adults, children, and babies).

  5. Scatter plot: to analyze the impact of additional service options (meal, required_car_parking_spaces, and total_of_special_requests) on ADR (adr)

  6. 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.