Load Required Libraries

library(ggplot2)
library(dplyr)
library(lubridate)
library(gridExtra)

Generate Sample Data

# Set seed for reproducibility
set.seed(123)

# Generate sample data spanning 2011-2016
dates <- seq(as.Date("2011-01-01"), as.Date("2016-12-31"), by = "week")
n <- length(dates)

# Create weekly sales data with seasonal patterns
weekly_data <- data.frame(
  Date = dates,
  Sales = 300000 + 50000 * sin(2 * pi * as.numeric(dates - min(dates)) / 365.25) +
    rnorm(n, 0, 30000)
)

# Create quarterly aggregated data
quarterly_data <- weekly_data %>%
  mutate(Quarter = quarter(Date, with_year = TRUE)) %>%
  group_by(Quarter) %>%
  summarise(
    Date = mean(Date),
    Sales = mean(Sales),
    .groups = "drop"
  )

# Create monthly aggregated data
monthly_data <- weekly_data %>%
  mutate(Month = floor_date(Date, "month")) %>%
  group_by(Month) %>%
  summarise(
    Date = Month,
    Sales = mean(Sales),
    .groups = "drop"
  )

Custom Plotting Function

# Function to create time series plot with smoothed line
create_ts_plot <- function(data, title, y_max = 800000) {
  p <- ggplot(data, aes(x = Date, y = Sales)) +
    geom_point(size = 1.5, alpha = 0.6) +
    geom_smooth(method = "loess", se = TRUE, color = "blue", 
                fill = "lightblue", alpha = 0.3, span = 0.3) +
    scale_y_continuous(
      labels = scales::dollar_format(scale = 1e-3, suffix = "K"),
      limits = c(0, y_max)
    ) +
    scale_x_date(date_breaks = "1 year", date_labels = "%Y") +
    labs(
      title = title,
      x = NULL,
      y = "Revenue (USD)"
    ) +
    theme_minimal() +
    theme(
      plot.title = element_text(hjust = 0.5, size = 12, face = "bold"),
      panel.grid.major = element_line(color = "gray90"),
      panel.grid.minor = element_blank(),
      axis.text = element_text(size = 10),
      axis.title.y = element_text(size = 10)
    )
  
  return(p)
}

Total Sales Charts

Category Sales Charts

Generate Category Data

# Categories and colors
categories <- c("Cross Country Race", "Over Mountain", "Trail", "Sport", "Fat Bike")
colors <- c("darkslategray", "red", "turquoise", "tan", "lightblue")

# Function to create category-specific data
create_category_data <- function(base_sales, amplitude, dates) {
  data.frame(
    Date = dates,
    Sales = base_sales + amplitude * sin(2 * pi * as.numeric(dates - min(dates)) / 365.25) +
      rnorm(length(dates), 0, amplitude * 0.3)
  )
}

# Weekly category data
weekly_cat_data <- bind_rows(
  create_category_data(100000, 20000, dates) %>% mutate(Category = categories[1]),
  create_category_data(80000, 15000, dates) %>% mutate(Category = categories[2]),
  create_category_data(70000, 18000, dates) %>% mutate(Category = categories[3]),
  create_category_data(60000, 12000, dates) %>% mutate(Category = categories[4]),
  create_category_data(50000, 10000, dates) %>% mutate(Category = categories[5])
)

# Convert Category to factor with specific order
weekly_cat_data$Category <- factor(weekly_cat_data$Category, levels = categories)

Sales By Category 2 - Weekly

p_cat_weekly <- ggplot(weekly_cat_data, aes(x = Date, y = Sales, color = Category, fill = Category)) +
  geom_point(size = 1, alpha = 0.5) +
  geom_smooth(method = "loess", se = TRUE, alpha = 0.2, span = 0.2) +
  facet_wrap(~ Category, ncol = 1, scales = "free_y", strip.position = "top") +
  scale_color_manual(values = colors) +
  scale_fill_manual(values = colors) +
  scale_y_continuous(labels = scales::dollar_format(scale = 1e-3, suffix = "K")) +
  scale_x_date(date_breaks = "2 years", date_labels = "%Y") +
  labs(
    title = "Sales By Category 2\nWeekly",
    x = NULL,
    y = NULL
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(hjust = 0.5, size = 14, face = "bold"),
    strip.background = element_rect(fill = "darkslategray", color = NA),
    strip.text = element_text(color = "white", face = "bold", size = 10),
    panel.grid.major = element_line(color = "gray90"),
    panel.grid.minor = element_blank(),
    legend.position = "none",
    panel.spacing = unit(0.5, "lines")
  )

print(p_cat_weekly)

Monthly Category Sales

# Create monthly category data
monthly_cat_data <- weekly_cat_data %>%
  mutate(Month = floor_date(Date, "month")) %>%
  group_by(Month, Category) %>%
  summarise(
    Date = Month,
    Sales = mean(Sales),
    .groups = "drop"
  )
p_cat_monthly <- ggplot(monthly_cat_data, aes(x = Date, y = Sales, color = Category, fill = Category)) +
  geom_point(size = 2, alpha = 0.6) +
  geom_smooth(method = "loess", se = TRUE, alpha = 0.2, span = 0.3) +
  facet_wrap(~ Category, ncol = 1, scales = "free_y", strip.position = "top") +
  scale_color_manual(values = colors) +
  scale_fill_manual(values = colors) +
  scale_y_continuous(labels = scales::dollar_format(scale = 1e-3, suffix = "K")) +
  scale_x_date(date_breaks = "2 years", date_labels = "%Y") +
  labs(
    title = "Sales By Category 2\nMonthly",
    x = NULL,
    y = NULL
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(hjust = 0.5, size = 14, face = "bold"),
    strip.background = element_rect(fill = "darkslategray", color = NA),
    strip.text = element_text(color = "white", face = "bold", size = 10),
    panel.grid.major = element_line(color = "gray90"),
    panel.grid.minor = element_blank(),
    legend.position = "none",
    panel.spacing = unit(0.5, "lines")
  )

print(p_cat_monthly)

Quarterly Category Sales

# Create quarterly category data
quarterly_cat_data <- weekly_cat_data %>%
  mutate(Quarter = quarter(Date, with_year = TRUE)) %>%
  group_by(Quarter, Category) %>%
  summarise(
    Date = mean(Date),
    Sales = mean(Sales),
    .groups = "drop"
  )
p_cat_quarterly <- ggplot(quarterly_cat_data, aes(x = Date, y = Sales, color = Category, fill = Category)) +
  geom_point(size = 3, alpha = 0.8) +
  geom_smooth(method = "loess", se = FALSE, linewidth = 1.5, span = 0.5) +
  facet_wrap(~ Category, ncol = 1, scales = "free_y", strip.position = "top") +
  scale_color_manual(values = colors) +
  scale_fill_manual(values = colors) +
  scale_y_continuous(labels = scales::dollar_format(scale = 1e-3, suffix = "K")) +
  scale_x_date(date_breaks = "1 year", date_labels = "%Y") +
  labs(
    title = "Sales By Category 2\nQuarterly",
    x = NULL,
    y = NULL
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(hjust = 0.5, size = 14, face = "bold"),
    strip.background = element_rect(fill = "darkslategray", color = NA),
    strip.text = element_text(color = "white", face = "bold", size = 10),
    panel.grid.major = element_line(color = "gray90"),
    panel.grid.minor = element_blank(),
    legend.position = "none",
    panel.spacing = unit(0.5, "lines")
  )

print(p_cat_quarterly)

Summary Statistics

# Create summary table
summary_table <- weekly_cat_data %>%
  group_by(Category) %>%
  summarise(
    Mean_Sales = mean(Sales),
    Median_Sales = median(Sales),
    SD_Sales = sd(Sales),
    Min_Sales = min(Sales),
    Max_Sales = max(Sales),
    .groups = "drop"
  ) %>%
  mutate(across(where(is.numeric), ~scales::dollar(.x, accuracy = 1)))

knitr::kable(summary_table, caption = "Sales Summary by Category")
Sales Summary by Category
Category Mean_Sales Median_Sales SD_Sales Min_Sales Max_Sales
Cross Country Race $99,976 $99,689 $15,782 $64,527 $131,228
Over Mountain $80,277 $78,444 $11,664 $55,935 $107,074
Trail $69,943 $68,879 $13,726 $40,220 $102,109
Sport $60,172 $60,128 $9,245 $42,674 $83,932
Fat Bike $50,105 $49,953 $7,477 $34,565 $64,813

Session Info

sessionInfo()
## R version 4.5.2 (2025-10-31)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 20.04.6 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3 
## LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/liblapack.so.3;  LAPACK version 3.9.0
## 
## locale:
##  [1] LC_CTYPE=C.UTF-8       LC_NUMERIC=C           LC_TIME=C.UTF-8       
##  [4] LC_COLLATE=C.UTF-8     LC_MONETARY=C.UTF-8    LC_MESSAGES=C.UTF-8   
##  [7] LC_PAPER=C.UTF-8       LC_NAME=C              LC_ADDRESS=C          
## [10] LC_TELEPHONE=C         LC_MEASUREMENT=C.UTF-8 LC_IDENTIFICATION=C   
## 
## time zone: UTC
## tzcode source: system (glibc)
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
## [1] gridExtra_2.3   lubridate_1.9.4 dplyr_1.1.4     ggplot2_4.0.1  
## 
## loaded via a namespace (and not attached):
##  [1] Matrix_1.7-4       gtable_0.3.6       jsonlite_2.0.0     compiler_4.5.2    
##  [5] tidyselect_1.2.1   jquerylib_0.1.4    splines_4.5.2      scales_1.4.0      
##  [9] yaml_2.3.11        fastmap_1.2.0      lattice_0.22-7     R6_2.6.1          
## [13] labeling_0.4.3     generics_0.1.4     knitr_1.50         tibble_3.3.0      
## [17] bslib_0.9.0        pillar_1.11.1      RColorBrewer_1.1-3 rlang_1.1.6       
## [21] cachem_1.1.0       xfun_0.54          sass_0.4.10        S7_0.2.1          
## [25] timechange_0.3.0   cli_3.6.5          withr_3.0.2        magrittr_2.0.4    
## [29] mgcv_1.9-3         digest_0.6.39      grid_4.5.2         rstudioapi_0.17.1 
## [33] lifecycle_1.0.4    nlme_3.1-168       vctrs_0.6.5        evaluate_1.0.5    
## [37] glue_1.8.0         farver_2.1.2       rmarkdown_2.30     tools_4.5.2       
## [41] pkgconfig_2.0.3    htmltools_0.5.9