Data Import and Preparation
# Read Excel file
bike_data <- read_excel("bike_orderlines.xlsx")
# Data preprocessing
bike_data <- bike_data %>%
mutate(
order_date = as.Date(order_date),
year_val = year(order_date),
quarter_val = quarter(order_date),
month_val = month(order_date),
qtr_date = floor_date(order_date, "quarter"),
month_date = floor_date(order_date, "month"),
week_date = floor_date(order_date, "week")
)
# Display data structure
glimpse(bike_data)
## Rows: 15,644
## Columns: 19
## $ order_date <date> 2011-01-07, 2011-01-07, 2011-01-10, 2011-01-10, 2011-0…
## $ order_id <dbl> 1, 1, 2, 2, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7…
## $ order_line <dbl> 1, 2, 1, 2, 1, 2, 3, 4, 5, 1, 1, 2, 3, 4, 1, 2, 3, 4, 1…
## $ quantity <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1…
## $ price <dbl> 6070, 5970, 2770, 5970, 10660, 3200, 12790, 5330, 1570,…
## $ total_price <dbl> 6070, 5970, 2770, 5970, 10660, 3200, 12790, 5330, 1570,…
## $ model <chr> "Jekyll Carbon 2", "Trigger Carbon 2", "Beast of the Ea…
## $ category_1 <chr> "Mountain", "Mountain", "Mountain", "Mountain", "Road",…
## $ category_2 <chr> "Over Mountain", "Over Mountain", "Trail", "Over Mounta…
## $ frame_material <chr> "Carbon", "Carbon", "Aluminum", "Carbon", "Carbon", "Ca…
## $ bikeshop_name <chr> "Ithaca Mountain Climbers", "Ithaca Mountain Climbers",…
## $ city <chr> "Ithaca", "Ithaca", "Kansas City", "Kansas City", "Loui…
## $ state <chr> "NY", "NY", "KS", "KS", "KY", "KY", "KY", "KY", "KY", "…
## $ year_val <dbl> 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2…
## $ quarter_val <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
## $ month_val <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
## $ qtr_date <date> 2011-01-01, 2011-01-01, 2011-01-01, 2011-01-01, 2011-0…
## $ month_date <date> 2011-01-01, 2011-01-01, 2011-01-01, 2011-01-01, 2011-0…
## $ week_date <date> 2011-01-02, 2011-01-02, 2011-01-09, 2011-01-09, 2011-0…
Part 2: Category-Specific Analysis
2.2 Road Bikes - Monthly Trends
# Monthly road bike data
road_month <- bike_data %>%
filter(category_1 == "Road") %>%
group_by(month_date, category_2) %>%
summarise(revenue = sum(total_price), .groups = "drop") %>%
mutate(category_2 = factor(
category_2,
levels = c("Elite Road", "Endurance Road", "Triathalon", "Cyclocross")
))
# Create bright color palette for road bikes
road_bright_colors <- c(
"Elite Road" = "#FF6B6B", # Bright red
"Endurance Road" = "#4ECDC4", # Bright teal
"Triathalon" = "#45B7D1", # Bright blue
"Cyclocross" = "#FFA07A" # Bright coral
)
# Plot - BRIGHT COLORS AND VISIBLE POINTS
ggplot(road_month, aes(x = month_date, y = revenue)) +
geom_point(aes(color = category_2), alpha = 0.7, size = 1.8, show.legend = FALSE) +
geom_smooth(
aes(color = category_2),
method = "loess",
se = FALSE,
span = 0.2,
size = 1.5,
show.legend = FALSE
) +
scale_color_manual(values = road_bright_colors) +
scale_y_continuous(labels = dollar_format()) +
scale_x_date(date_breaks = "1 year", date_labels = "%Y") +
facet_wrap(~category_2, ncol = 1, scales = "free_y") +
labs(
title = "Road Bikes - Monthly Sales Patterns",
x = NULL,
y = "Revenue"
) +
theme_bw(base_size = 12) +
theme(
plot.title = element_text(size = 15, face = "bold", hjust = 0.5),
plot.background = element_rect(fill = "#F5F5F5", color = NA),
panel.background = element_rect(fill = "#F5F5F5", color = NA),
strip.background = element_rect(fill = "#D1D5DB"),
strip.text = element_text(color = "black", face = "bold", size = 11),
panel.grid.minor = element_blank(),
panel.grid.major = element_line(color = "gray80")
)

2.3 Road Bikes - Weekly Fluctuations
# Weekly road bike data
road_week <- bike_data %>%
filter(category_1 == "Road") %>%
group_by(week_date, category_2) %>%
summarise(revenue = sum(total_price), .groups = "drop") %>%
mutate(category_2 = factor(
category_2,
levels = c("Elite Road", "Endurance Road", "Triathalon", "Cyclocross")
))
# Create plot - BRIGHT COLORS
ggplot(road_week, aes(x = week_date, y = revenue)) +
geom_point(aes(color = category_2), alpha = 0.6, size = 1.5, show.legend = FALSE) +
geom_smooth(
aes(color = category_2),
method = "loess",
se = FALSE,
span = 0.2,
size = 1.5,
show.legend = FALSE
) +
scale_color_manual(values = road_bright_colors) +
scale_y_continuous(labels = dollar_format()) +
scale_x_date(date_breaks = "1 year", date_labels = "%Y") +
facet_wrap(~category_2, ncol = 1, scales = "free_y") +
labs(
title = "Road Bikes - Weekly Sales Dynamics",
x = NULL,
y = "Revenue"
) +
theme_bw(base_size = 12) +
theme(
plot.title = element_text(size = 15, face = "bold", hjust = 0.5),
plot.background = element_rect(fill = "#F5F5F5", color = NA),
panel.background = element_rect(fill = "#F5F5F5", color = NA),
strip.background = element_rect(fill = "#D1D5DB"),
strip.text = element_text(color = "black", face = "bold", size = 11),
panel.grid.minor = element_blank(),
panel.grid.major = element_line(color = "gray80")
)

2.5 Mountain Bikes - Monthly Trends
# Monthly mountain bike data
mountain_month <- bike_data %>%
filter(category_1 == "Mountain") %>%
group_by(month_date, category_2) %>%
summarise(revenue = sum(total_price), .groups = "drop") %>%
mutate(category_2 = factor(
category_2,
levels = c("Cross Country Race", "Trail", "Over Mountain", "Sport", "Fat Bike")
))
# Create bright color palette for mountain bikes
mountain_bright_colors_named <- c(
"Cross Country Race" = "#FF6B6B", # Bright red
"Trail" = "#4ECDC4", # Bright teal
"Over Mountain" = "#45B7D1", # Bright blue
"Sport" = "#FFA07A", # Bright coral
"Fat Bike" = "#96CEB4" # Bright mint green
)
# Plot - BRIGHT COLORS AND VISIBLE POINTS
ggplot(mountain_month, aes(x = month_date, y = revenue)) +
geom_point(aes(color = category_2), alpha = 0.7, size = 1.8, show.legend = FALSE) +
geom_smooth(
aes(color = category_2),
method = "loess",
se = FALSE,
span = 0.2,
size = 1.5,
show.legend = FALSE
) +
scale_color_manual(values = mountain_bright_colors_named) +
scale_y_continuous(labels = dollar_format()) +
scale_x_date(date_breaks = "1 year", date_labels = "%Y") +
facet_wrap(~category_2, ncol = 1, scales = "free_y") +
labs(
title = "Mountain Bikes - Monthly Sales Patterns",
x = NULL,
y = "Revenue"
) +
theme_bw(base_size = 12) +
theme(
plot.title = element_text(size = 15, face = "bold", hjust = 0.5),
plot.background = element_rect(fill = "#F5F5F5", color = NA),
panel.background = element_rect(fill = "#F5F5F5", color = NA),
strip.background = element_rect(fill = "#D1D5DB"),
strip.text = element_text(color = "black", face = "bold", size = 11),
panel.grid.minor = element_blank(),
panel.grid.major = element_line(color = "gray80")
)

2.6 Mountain Bikes - Weekly Fluctuations
# Weekly mountain bike data
mountain_week <- bike_data %>%
filter(category_1 == "Mountain") %>%
group_by(week_date, category_2) %>%
summarise(revenue = sum(total_price), .groups = "drop") %>%
mutate(category_2 = factor(
category_2,
levels = c("Cross Country Race", "Trail", "Over Mountain", "Sport", "Fat Bike")
))
# Create plot - BRIGHT COLORS
ggplot(mountain_week, aes(x = week_date, y = revenue)) +
geom_point(aes(color = category_2), alpha = 0.6, size = 1.5, show.legend = FALSE) +
geom_smooth(
aes(color = category_2),
method = "loess",
se = FALSE,
span = 0.2,
size = 1.5,
show.legend = FALSE
) +
scale_color_manual(values = mountain_bright_colors_named) +
scale_y_continuous(labels = dollar_format()) +
scale_x_date(date_breaks = "1 year", date_labels = "%Y") +
facet_wrap(~category_2, ncol = 1, scales = "free_y") +
labs(
title = "Mountain Bikes - Weekly Sales Dynamics",
x = NULL,
y = "Revenue"
) +
theme_bw(base_size = 12) +
theme(
plot.title = element_text(size = 15, face = "bold", hjust = 0.5),
plot.background = element_rect(fill = "#F5F5F5", color = NA),
panel.background = element_rect(fill = "#F5F5F5", color = NA),
strip.background = element_rect(fill = "#D1D5DB"),
strip.text = element_text(color = "black", face = "bold", size = 11),
panel.grid.minor = element_blank(),
panel.grid.major = element_line(color = "gray80")
)
