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
:———- :—————- ———–: