If you have any questions regarding the assignment instructions and the R Markdown template, please post it on the discussion board Questions on completing Assessment 2.
library(dplyr): Manipulating data allows for merging datasets, creating columns, filtering data. library(tidyr): cleaning up and reorganising data library(lubridate): orchestrates working with dates and times library(ggplot2): Implementation of graph visualisations library(knitr): Report documentation
Insert and load the packages you need to produce the report here:
library(magrittr)
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(tidyr)
##
## Attaching package: 'tidyr'
## The following object is masked from 'package:magrittr':
##
## extract
library(lubridate)
##
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
##
## date, intersect, setdiff, union
library(ggplot2)
library(knitr)
Follow the instructions given in the Assessment brief to fill out the template below. Remember to include R codes and outputs and explain your working and results in plain text.
Write your plain text here.
You may use a bullet list like this:
represents individual uber ride bookings. Each row represents one
booking and contains 80 observations across 9 variables. Includes
booking/customer IDs, date and time, booking status, vehicle type,
payment method, ride distance and booking value. - sample size: creates
object called n giving it a value of 80. n communicates how many
observations the user intends to generate. - seed result: seed was set
so the same random data is generated each time. - create booking IDs:
paste0(“B”) pastes B in front of 1:N all the way up to 80 observations -
Create customer IDs: customer_id <- creates a variable that stores
the results. past0(“c”, 1:60) creates 60 customer IDS. Sample() randomly
selects from these customers, while n represents the 80 booking
observations. replace = TRUE allows the same customer to be selected
more than once. - Generate booking dates: date <- creates a variable
called date and stores the formed data inside.Sample going to randomly
select something. Seq notifies sample the range from which it can select
from dates. as.date sets the date time period start to finish. n selects
80 dates due to 80 observations. Replace = True indicates a date can be
selected more than once. - Generate booking dates: time <- creates a
variable column named time. Paste0 joins pieces together. sample randly
selects an hour from (0:23 to 80 times, 80 indicated by n. Replace =
True indicates can be repeated. “:” indicates place colon inbetween hour
and minutes. hours is indicated first followed by minutes described in
military time. - Generate booking status: booking_status <- Create
variable name called book status to store data inside. Sample() tells r
to randomly select values. C(“completed”, “cancelled”, “incomplete”) c
representing combine in R in compiling a vector list of choices such as
completed, cancelled and incomplete. 3 possible booking statuses which r
can select from. N indicating make 80 selections based on the 80
observations of the booking. Replace = True, statuses can be chosen
multiple times. - Generate ride distance using a evenly spread
distribution: ride distance <- creates variables called ride_distance
to store generated data in. runif() generates random numbers spread out
across a specific range. N generates 80 values (observations.) min = 2
sets the smallest distance the runif can be generated to 2km and max =
35 is the largest distance 35km. - ride_distance_km: ride_distance_km
<- round(ride_distance, digits = 1) within ride_distance_km store the
rounded 1 decimal digits within riding_distance_km. - Generate
correlated booking values: a <- 5 indicates starting base price. b
<- 2 the increase of cost per distance, $2 per km. S <- 4 standard
deviation indicates randomness. This allows for longer ride distances to
be valued at a higher rate. - Generate random error: creates a variable
called error. rnorm() generates random numbers from no preconceived
numbers. n, generate 80 random numbers. Mean = 0 centre the numbers
around 0. SD = s, standard deviation and s = 4 based on previous
commands. - Booking value on ride distance and random error:
booking_value <-. create a variable called booking_value to store the
calculated prices. a is the starting base of 5 + B ride distance $2 per
km + error to add random variation. then round each bookign value to 2
decimal digits.
- Create the dataset: take the entirety of the data set variables
created and form them into a data frame titled uber_bookings. - Display
observations: show me the first couple variables/rows of data.frame
created.
# sample size
n <- 80
# seed result for reproduction
SEED <- 123
set.seed(SEED)
# Create booking IDs
booking_id <- paste0("B", 1:n)
# Create customer IDs
customer_id <- sample(
paste0("c", 1:60),
n,
replace = TRUE
)
# Generate booking dates
date <- sample(
seq(as.Date("2026-01-01"), as.Date("2026-03-31"), by = "day"),
n,
replace = TRUE
)
# Generate booking times
time <- paste0(
sample (0:23, n, replace = TRUE), # Hours
":",
sample(0:59, n, replace = TRUE) # Minutes
)
# Generate booking status
booking_status <-sample(
c("Completed", "Cancelled", "Incomplete"),
n,
replace = TRUE
)
# Generate vehicle type
vehicle_type <- sample(
c("UberX", "Comfort", "UberXL"),
n,
replace = TRUE
)
# Generate payment method
payment_method <- sample(
c("Card", "paypal", "Cash"),
n,
replace = TRUE
)
# Generate ride distance using a evenly spread distribution
ride_distance_km <- runif(
n,
min = 2,
max = 35
)
ride_distance_km <- round(ride_distance_km, digits = 1)
# Generate correlated booking values
# set the intercept
a <- 5
# set the slope
b <- 2
s <- 4
# Generate random error
error <- rnorm(
n,
mean = 0,
sd = s
)
# Booking value on ride distance and random error
booking_value <- a + b * ride_distance_km + error
booking_value <- round(booking_value, digits = 2)
# Add outliers to numeric variables
booking_value[1] <- 200
ride_distance_km[2] <- 100
# Add 3 missing values
booking_status[10] <- NA
payment_method[20] <- NA
ride_distance_km[30] <- NA
# Create the dataset
uber_bookings <- data.frame(
booking_id,
customer_id,
date,
time,
booking_status,
vehicle_type,
booking_value,
ride_distance_km,
payment_method
)
colSums(is.na(uber_bookings))
## booking_id customer_id date time
## 0 0 0 0
## booking_status vehicle_type booking_value ride_distance_km
## 1 0 0 1
## payment_method
## 1
# Display observations
head(uber_bookings)
# setting sample size
n_customers <-60
# set a different seed
SEED2 <- 456
set.seed(SEED2)
# Create customer IDs
customer_id <-paste0("c", 1:n_customers)
# Generate customer ratings
customer_rating <- runif(
n_customers,
min = 3.5,
max = 5
)
customer_rating <- round(customer_rating, digits = 1)
# Generate number of cancelled rides
cancelled_rides <- sample(
0:4,
n_customers,
replace = TRUE
)
# Generate number of incomplete rides
incomplete_rides <- sample(
0:2,
n_customers,
replace = TRUE
)
# Add outliers to numeric variables
customer_rating[customer_id == "c3"] <- 1.5
cancelled_rides[customer_id == "c5"] <- 15
incomplete_rides[customer_id == "c6"] <- 8
#generate cancellation reasons
Cancellation_reason <-ifelse(
cancelled_rides ==0,
"no cancellations",
sample(
c("Driver too far away",
"Changed plans",
"Incorrect pick up location",
"Long wait time"),
n_customers,
replace = TRUE
)
)
# Generate city
city <- sample(
c("Adelaide", "Melbourne", "Sydney", "Brisbane"),
n_customers,
replace = TRUE
)
# Generate membership type
membership_type <- sample (
c("standard","uber one"),
n_customers,
replace = TRUE
)
# 3 missing values
customer_rating[10] <- NA
Cancellation_reason[18] <- NA
city[25] <- NA
# Dataset
uber_customers <-data.frame(
customer_id,
customer_rating,
cancelled_rides,
Cancellation_reason,
incomplete_rides,
city,
membership_type
)
# Observation data.frame
head(uber_customers)
Create a new data frame called uber_data and store the merged data inside. Start with uber_bookings, then use left_join() to add matching information from uber_customers using customer_id. - uber_data <- store the result here - Uber_bookings: use this data set first - %>% then onto next step - left join (uber_customers) add matching data from uber customers - by = “customer_id” use customer_id to match rows. Using customer ID to see what matches with what.
uber_data <- uber_bookings %>%
left_join(uber_customers, by ="customer_id")
head(uber_data)
# missing values
colSums(is.na(uber_data))
## booking_id customer_id date time
## 0 0 0 0
## booking_status vehicle_type booking_value ride_distance_km
## 1 0 0 1
## payment_method customer_rating cancelled_rides Cancellation_reason
## 1 1 0 1
## incomplete_rides city membership_type
## 0 3 0
# booking_status
uber_data$booking_status <- as.character(uber_data$booking_status)
uber_data$booking_status[is.na(uber_data$booking_status)] <- "unknown"
uber_data$booking_status <- as.factor(uber_data$booking_status)
# Ride_distance_km
uber_data$ride_distance_km[is.na(uber_data$ride_distance_km)] <-
mean(uber_data$ride_distance_km, na.rm = TRUE)
# payment_method
uber_data$payment_method <- as.character(uber_data$payment_method)
uber_data$payment_method[is.na(uber_data$payment_method)] <- "unknown"
uber_data$payment_method <- as.factor(uber_data$payment_method)
# remaining values
colSums(is.na(uber_data))
## booking_id customer_id date time
## 0 0 0 0
## booking_status vehicle_type booking_value ride_distance_km
## 0 0 0 0
## payment_method customer_rating cancelled_rides Cancellation_reason
## 0 1 0 1
## incomplete_rides city membership_type
## 0 3 0
# Inspect merged dataset uber_data
# Inspect data type, variable structures.
uber_data %>% str()
## 'data.frame': 80 obs. of 15 variables:
## $ booking_id : chr "B1" "B2" "B3" "B4" ...
## $ customer_id : chr "c31" "c15" "c51" "c14" ...
## $ date : Date, format: "2026-03-13" "2026-03-27" ...
## $ time : chr "7:5" "19:49" "15:29" "23:30" ...
## $ booking_status : Factor w/ 4 levels "Cancelled","Completed",..: 2 3 1 3 1 2 1 1 1 4 ...
## $ vehicle_type : chr "Comfort" "UberX" "UberX" "UberXL" ...
## $ booking_value : num 200 16.1 25.2 62.6 72.2 ...
## $ ride_distance_km : num 32.5 100 12.4 28.5 34.6 12.6 2 34.7 6.9 3.6 ...
## $ payment_method : Factor w/ 4 levels "Card","Cash",..: 2 1 1 2 2 2 2 3 1 1 ...
## $ customer_rating : num 5 4.4 4.8 4.7 1.5 4.1 4.9 4.1 3.6 5 ...
## $ cancelled_rides : num 4 4 2 0 1 4 2 4 0 3 ...
## $ Cancellation_reason: chr "Incorrect pick up location" "Driver too far away" "Changed plans" "no cancellations" ...
## $ incomplete_rides : num 2 1 2 0 0 0 2 2 0 2 ...
## $ city : chr "Melbourne" "Adelaide" "Adelaide" "Brisbane" ...
## $ membership_type : chr "uber one" "uber one" "standard" "uber one" ...
# convert data type, variable structures.
uber_data <- uber_data %>%
mutate(
booking_status = as.factor(booking_status),
vehicle_type = as.factor(vehicle_type),
payment_method = as.factor(payment_method),
Cancellation_reason = as.factor(Cancellation_reason),
city = as.factor(city),
membership_type = as.factor(membership_type)
)
# display data type, variable structures.
str(uber_data)
## 'data.frame': 80 obs. of 15 variables:
## $ booking_id : chr "B1" "B2" "B3" "B4" ...
## $ customer_id : chr "c31" "c15" "c51" "c14" ...
## $ date : Date, format: "2026-03-13" "2026-03-27" ...
## $ time : chr "7:5" "19:49" "15:29" "23:30" ...
## $ booking_status : Factor w/ 4 levels "Cancelled","Completed",..: 2 3 1 3 1 2 1 1 1 4 ...
## $ vehicle_type : Factor w/ 3 levels "Comfort","UberX",..: 1 2 2 3 2 1 1 3 1 2 ...
## $ booking_value : num 200 16.1 25.2 62.6 72.2 ...
## $ ride_distance_km : num 32.5 100 12.4 28.5 34.6 12.6 2 34.7 6.9 3.6 ...
## $ payment_method : Factor w/ 4 levels "Card","Cash",..: 2 1 1 2 2 2 2 3 1 1 ...
## $ customer_rating : num 5 4.4 4.8 4.7 1.5 4.1 4.9 4.1 3.6 5 ...
## $ cancelled_rides : num 4 4 2 0 1 4 2 4 0 3 ...
## $ Cancellation_reason: Factor w/ 5 levels "Changed plans",..: 3 2 1 5 1 4 2 3 5 2 ...
## $ incomplete_rides : num 2 1 2 0 0 0 2 2 0 2 ...
## $ city : Factor w/ 4 levels "Adelaide","Brisbane",..: 3 1 1 2 1 3 3 3 2 1 ...
## $ membership_type : Factor w/ 2 levels "standard","uber one": 2 2 1 2 1 1 2 1 2 2 ...
# display statistic summary in Q1, Q2 and Q3.
uber_data %>% summary()
## booking_id customer_id date time
## Length :80 Length :80 Min. :2026-01-01 Length :80
## N.unique :80 N.unique :44 1st Qu.:2026-01-25 N.unique :77
## N.blank : 0 N.blank : 0 Median :2026-02-15 N.blank : 0
## Min.nchar: 2 Min.nchar: 2 Mean :2026-02-17 Min.nchar: 3
## Max.nchar: 3 Max.nchar: 3 3rd Qu.:2026-03-15 Max.nchar: 5
## Max. :2026-03-31
##
## booking_status vehicle_type booking_value ride_distance_km
## Cancelled :30 Comfort:32 Min. : 3.27 Min. : 2.00
## Completed :24 UberX :20 1st Qu.: 21.20 1st Qu.: 10.10
## Incomplete:25 UberXL :28 Median : 39.70 Median : 17.65
## unknown : 1 Mean : 40.21 Mean : 18.32
## 3rd Qu.: 54.20 3rd Qu.: 24.90
## Max. :200.00 Max. :100.00
##
## payment_method customer_rating cancelled_rides
## Card :23 Min. :1.500 Min. : 0.000
## Cash :31 1st Qu.:3.900 1st Qu.: 0.000
## paypal :25 Median :4.400 Median : 2.000
## unknown: 1 Mean :4.322 Mean : 2.275
## 3rd Qu.:4.800 3rd Qu.: 3.250
## Max. :5.000 Max. :15.000
## NAs :1
## Cancellation_reason incomplete_rides city
## Changed plans :21 Min. :0.000 Adelaide :16
## Driver too far away :19 1st Qu.:0.000 Brisbane :24
## Incorrect pick up location:10 Median :1.000 Melbourne:26
## Long wait time : 9 Mean :0.925 Sydney :11
## no cancellations :20 3rd Qu.:2.000 NAs : 3
## NAs : 1 Max. :8.000
##
## membership_type
## standard:30
## uber one:50
##
##
##
##
##
# names of variables
names(uber_data)
## [1] "booking_id" "customer_id" "date"
## [4] "time" "booking_status" "vehicle_type"
## [7] "booking_value" "ride_distance_km" "payment_method"
## [10] "customer_rating" "cancelled_rides" "Cancellation_reason"
## [13] "incomplete_rides" "city" "membership_type"
# This is a chunk where you inspect the types of variables, data structures, check the attributes in the data and apply proper data type conversions
A new variable was created named vehicle category. This was created from the existing different car types Uber supplies. UberX is categorised as standard, comfort as comfort and UberXL as larger vehicle.
uber_data <- uber_data %>%
mutate(
vehicle_category = case_when(
vehicle_type == "UberX" ~ "Standard",
vehicle_type == "Comfort" ~ "Comfort",
vehicle_type == "UberXL" ~ "Larger Vehicle",
)
)
head(uber_data)
colSums(is.na(uber_data)): (is.na find the missing na within the uber_data) once this is done count the missing values in each column. Find the Nas and count them by column.
Numeric data is often replaced with the mean
categorical variable replace the missing value with unknown.
colSums(is.na(uber_data))
## booking_id customer_id date time
## 0 0 0 0
## booking_status vehicle_type booking_value ride_distance_km
## 0 0 0 0
## payment_method customer_rating cancelled_rides Cancellation_reason
## 0 1 0 1
## incomplete_rides city membership_type vehicle_category
## 0 3 0 0
colSums(uber_data == "", na.rm = TRUE)
## booking_id customer_id date time
## 0 0 0 0
## booking_status vehicle_type booking_value ride_distance_km
## 0 0 0 0
## payment_method customer_rating cancelled_rides Cancellation_reason
## 0 0 0 0
## incomplete_rides city membership_type vehicle_category
## 0 0 0 0
sum(uber_data$city == "Unknown", na.rm = TRUE)
## [1] 0
sum(uber_data$Cancellation_reason == "Unknown", na.rm = TRUE)
## [1] 0
# Convert missing numeric rating value to the average.
uber_data$customer_rating[is.na(uber_data$customer_rating)] <-
mean(uber_data$customer_rating, na.rm = TRUE)
sum(is.na(uber_data$customer_rating))
## [1] 0
# Convert factor to character
uber_data$Cancellation_reason <- as.character(uber_data$Cancellation_reason)
# Replace missing value with unknown
uber_data$Cancellation_reason[is.na(uber_data$Cancellation_reason)] <-"unknown"
#change back to factor
uber_data$Cancellation_reason <- as.factor(uber_data$Cancellation_reason)
table(uber_data$Cancellation_reason)
##
## Changed plans Driver too far away
## 21 19
## Incorrect pick up location Long wait time
## 10 9
## no cancellations unknown
## 20 1
uber_data$city <- as.character(uber_data$city)
uber_data$city[is.na(uber_data$city)] <- "unknown"
uber_data$city <- as.factor(uber_data$city)
table(uber_data$Cancellation_reason)
##
## Changed plans Driver too far away
## 21 19
## Incorrect pick up location Long wait time
## 10 9
## no cancellations unknown
## 20 1
sum(is.na(uber_data$Cancellation_reason))
## [1] 0
boxplots were uesed to scan the numeric variables for outliers. Outliers were identified in booking value (200), ride distance (100), customer rating (1.5), cancelled rides (15), and incomplete rides (8). The outliers were replaced with the mean of the remaining values for each variable. The boxplots were then checked again to confirm the extreme outliers had been treated.
Ride distance boxplot: Q1 (bottom of box): est 10km -> 25% of rides are 10km or less median (black line): est 17-18km ->average ride distance Q3 (top of box): about 25km ->75% are 25km or less max/top of whiskers: 35km outliers: removed none.
Cancelled rides boxplot: lowest: 0 Q1(25%): 0 median (50%): 2 cancelled rides Q3 (75%) 3 cancelled rides Highest: 4 cancelled rides outliers: removed none
Booking Value: booking values had a median of approx $40. The middle 50% of bookings ranged from approx $21 to 54, while the highest non-outlier booking value was approx $73. outliers removed.
sapply(uber_data, is.numeric)
## booking_id customer_id date time
## FALSE FALSE FALSE FALSE
## booking_status vehicle_type booking_value ride_distance_km
## FALSE FALSE TRUE TRUE
## payment_method customer_rating cancelled_rides Cancellation_reason
## FALSE TRUE TRUE FALSE
## incomplete_rides city membership_type vehicle_category
## TRUE FALSE FALSE FALSE
boxplot(uber_data$customer_rating,
main = "Customer Rating")
boxplot(uber_data$booking_value,
main = "booking value")
boxplot(uber_data$ride_distance_km,
main = "ride_distance_km")
boxplot(uber_data$cancelled_rides,
main = "cancelled_rides")
boxplot(uber_data$incomplete_rides,
main = "incomplete_rides")
max(uber_data$cancelled_rides)
## [1] 15
max(uber_customers$cancelled_rides)
## [1] 15
# outliers to Averages
uber_data$booking_value[uber_data$booking_value == 200] <-
mean(uber_data$booking_value[uber_data$booking_value != 200])
max(uber_data$booking_value)
## [1] 72.23
boxplot(uber_data$booking_value,
main = "booking Value")
#removing outliers
uber_data$ride_distance_km[uber_data$ride_distance_km == 100] <-
mean(uber_data$ride_distance_km[uber_data$ride_distance_km != 200])
max(uber_data$ride_distance_km)
## [1] 34.7
boxplot(uber_data$ride_distance_km,
main = "ride distance (km)")
#removing outliers
uber_data$customer_rating[uber_data$customer_rating == 1.5] <-
mean(uber_data$customer_rating[uber_data$customer_rating !=1.5])
min(uber_data$customer_rating)
## [1] 3.6
boxplot(uber_data$customer_rating,
main = "Customer Rating")
#removing outliers
uber_data$cancelled_rides[uber_data$cancelled_rides == 15] <-
mean(uber_data$cancelled_rides[uber_data$cancelled_rides !=15])
max(uber_data$cancelled_rides)
## [1] 4
boxplot(uber_data$cancelled_rides,
main = "cancelled rides")
#removing outliers
uber_data$incomplete_rides[uber_data$incomplete_rides == 8] <-
mean(uber_data$incomplete_rides[uber_data$incomplete_rides != 8])
max(uber_data$incomplete_rides)
## [1] 2
boxplot(uber_data$incomplete_rides,
main = "incomplete_rides")
Changing KM distance to M
uber_data <- uber_data %>%
mutate(
ride_distance_m = ride_distance_km * 1000
)
head(uber_data[, c("ride_distance_km", "ride_distance_m")])
Vehicle category: Standard had the highest average rating at 4.46, followed by larger vehicle at 4.34 and comfort at 4.31. Distance vs rating: correlation = 0.036, meaning no relationship between ride distance and customer rating. City: Adleaide had the highest average rating at 4.54, followed by Melbourne 4.40, Sydney 4.31, and Brisbane 4.15. Total booking valuey = $3,054.61 within the synethetic dataset.
# average rating based on vehicle type
uber_data %>%
group_by(vehicle_category) %>%
summarise(
average_rating = mean(customer_rating)
)
# reviews grouped by city
uber_data %>%
group_by(city) %>%
summarise(
average_rating = mean(customer_rating)
)
# Correlation between ride distance and customer rating
cor(uber_data$ride_distance_km, uber_data$customer_rating)
## [1] -0.03256928
# Booking value
sum(uber_data$booking_value)
## [1] 3054.613