library(completejourney)
## Welcome to the completejourney package! Learn more about these data
## sets at http://bit.ly/completejourney.
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.1 ✔ tibble 3.2.1
## ✔ lubridate 1.9.3 ✔ tidyr 1.3.1
## ✔ purrr 1.0.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(lubridate)
library(ggplot2)
library(knitr)
library(dplyr)
library(kableExtra)
##
## Attaching package: 'kableExtra'
##
## The following object is masked from 'package:dplyr':
##
## group_rows
library(stringr)
transactions <- get_transactions()
products <- products
str(transactions)
## tibble [1,469,307 × 11] (S3: tbl_df/tbl/data.frame)
## $ household_id : chr [1:1469307] "900" "900" "1228" "906" ...
## $ store_id : chr [1:1469307] "330" "330" "406" "319" ...
## $ basket_id : chr [1:1469307] "31198570044" "31198570047" "31198655051" "31198705046" ...
## $ product_id : chr [1:1469307] "1095275" "9878513" "1041453" "1020156" ...
## $ quantity : num [1:1469307] 1 1 1 1 2 1 1 1 1 1 ...
## $ sales_value : num [1:1469307] 0.5 0.99 1.43 1.5 2.78 5.49 1.5 1.88 1.5 2.69 ...
## $ retail_disc : num [1:1469307] 0 0.1 0.15 0.29 0.8 0.5 0.29 0.21 1.29 0 ...
## $ coupon_disc : num [1:1469307] 0 0 0 0 0 0 0 0 0 0 ...
## $ coupon_match_disc : num [1:1469307] 0 0 0 0 0 0 0 0 0 0 ...
## $ week : int [1:1469307] 1 1 1 1 1 1 1 1 1 1 ...
## $ transaction_timestamp: POSIXct[1:1469307], format: "2017-01-01 06:53:26" "2017-01-01 07:10:28" ...
transactions <- transactions %>%
mutate(transaction_timestamp = as.character(transaction_timestamp),
date_time = ymd_hms(transaction_timestamp),
date = as.Date(date_time),
time = format(date_time, format = "%H:%M:%S"),
year = year(date_time),
month = month(date_time),
day = day(date_time),
hour = hour(date_time),
minute = minute(date_time),
second = second(date_time))
head(transactions)
## # A tibble: 6 × 20
## household_id store_id basket_id product_id quantity sales_value retail_disc
## <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl>
## 1 900 330 31198570044 1095275 1 0.5 0
## 2 900 330 31198570047 9878513 1 0.99 0.1
## 3 1228 406 31198655051 1041453 1 1.43 0.15
## 4 906 319 31198705046 1020156 1 1.5 0.29
## 5 906 319 31198705046 1053875 2 2.78 0.8
## 6 906 319 31198705046 1060312 1 5.49 0.5
## # ℹ 13 more variables: coupon_disc <dbl>, coupon_match_disc <dbl>, week <int>,
## # transaction_timestamp <chr>, date_time <dttm>, date <date>, time <chr>,
## # year <dbl>, month <dbl>, day <int>, hour <int>, minute <int>, second <dbl>
# Define a holiday list
holidays <- tibble(
holiday_name = c("Thanksgiving", "Christmas", "4th of July"),
holiday_date = as.Date(c("2018-11-22", "2018-12-25", "2018-07-04"))
)
# Create a flag for holiday sales
transactions <- transactions %>%
left_join(holidays, by = c("date" = "holiday_date")) %>%
mutate(is_holiday = !is.na(holiday_name))
dim(transactions)
## [1] 1469307 22
head(transactions)
## # A tibble: 6 × 22
## household_id store_id basket_id product_id quantity sales_value retail_disc
## <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl>
## 1 900 330 31198570044 1095275 1 0.5 0
## 2 900 330 31198570047 9878513 1 0.99 0.1
## 3 1228 406 31198655051 1041453 1 1.43 0.15
## 4 906 319 31198705046 1020156 1 1.5 0.29
## 5 906 319 31198705046 1053875 2 2.78 0.8
## 6 906 319 31198705046 1060312 1 5.49 0.5
## # ℹ 15 more variables: coupon_disc <dbl>, coupon_match_disc <dbl>, week <int>,
## # transaction_timestamp <chr>, date_time <dttm>, date <date>, time <chr>,
## # year <dbl>, month <dbl>, day <int>, hour <int>, minute <int>, second <dbl>,
## # holiday_name <chr>, is_holiday <lgl>
# Join transactions with product data and filter for Bread and Soft Drinks
sales_data <- transactions %>%
inner_join(products, by = "product_id") %>%
filter(product_category %in% c("Bread", "Soft Drinks"))
dim(sales_data)
## [1] 0 28
head(sales_data)
## # A tibble: 0 × 28
## # ℹ 28 variables: household_id <chr>, store_id <chr>, basket_id <chr>,
## # product_id <chr>, quantity <dbl>, sales_value <dbl>, retail_disc <dbl>,
## # coupon_disc <dbl>, coupon_match_disc <dbl>, week <int>,
## # transaction_timestamp <chr>, date_time <dttm>, date <date>, time <chr>,
## # year <dbl>, month <dbl>, day <int>, hour <int>, minute <int>, second <dbl>,
## # holiday_name <chr>, is_holiday <lgl>, manufacturer_id <chr>,
## # department <chr>, brand <fct>, product_category <chr>, …
# Sales volume over time for Bread and Soft Drinks
sales_by_date <- sales_data %>%
group_by(date, product_category) %>%
summarise(total_sales = sum(sales_value, na.rm = TRUE), .groups = 'drop')
dim(sales_by_date)
## [1] 0 3
head(sales_by_date)
## # A tibble: 0 × 3
## # ℹ 3 variables: date <date>, product_category <chr>, total_sales <dbl>
# Check if sales_by_date has valid data before plotting
if (nrow(sales_by_date) > 0) {
ggplot(sales_by_date, aes(x = date, y = total_sales, color = product_category)) +
geom_line() +
labs(title = "Sales Volume Over Time for Bread and Soft Drinks",
x = "Date",
y = "Total Sales",
color = "Product Category") +
theme_minimal() +
scale_x_date(date_labels = "%b %d", date_breaks = "1 month") +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
} else {
message("No valid sales data available for plotting.")
}
## No valid sales data available for plotting.
# Create a summary for sales on holidays vs. non-holidays for Bread and Soft Drinks
holiday_sales_summary <- sales_data %>%
group_by(is_holiday, product_category) %>%
summarise(total_sales = sum(sales_value, na.rm = TRUE),
total_quantity = sum(quantity, na.rm = TRUE),
.groups = 'drop') %>%
arrange(desc(total_sales))
# Display the summary table for holiday vs. non-holiday sales
holiday_sales_summary %>%
kable(caption = "Sales Summary for Bread and Soft Drinks: Holidays vs. Non-Holidays") %>%
kable_styling(bootstrap_options = "striped", full_width = FALSE)
Sales Summary for Bread and Soft Drinks: Holidays vs. Non-Holidays
|
is_holiday
|
product_category
|
total_sales
|
total_quantity
|
|
NA
|
NA
|
NA
|
NA
|
|
:———-
|
:—————-
|
———–:
|
————–:
|
# Top-selling Bread and Soft Drinks during holidays
top_holiday_sales <- sales_data %>%
filter(is_holiday == TRUE) %>%
group_by(product_id, product_category) %>%
summarise(total_sales = sum(sales_value, na.rm = TRUE), .groups = 'drop') %>%
arrange(desc(total_sales)) %>%
head(10) # Get top 10 products
# Display the top-selling products table
top_holiday_sales %>%
kable(caption = "Top-Selling Bread and Soft Drinks During Holidays") %>%
kable_styling(bootstrap_options = "striped", full_width = FALSE)
Top-Selling Bread and Soft Drinks During Holidays
|
product_id
|
product_category
|
total_sales
|
|
NA
|
NA
|
NA
|
|
:———-
|
:—————-
|
———–:
|