Objective: Reproduce the “hour-of-week price change” graphs using RStudio.
Tools used:
Data from analysis_data.dta , data.table, ggplot2, and lubridate packages
Outcome: Understand retailer pricing behavior by hour and day of the week.
In this paper, Brown & MacKay (2023), show that pricing behavior varies significantly across retailers.
We used ggplot2 for plotting (Wickham (2016)) and built this deck with Quarto (Posit, PBC (2022)).
Replication Code
library(data.table)library(dplyr)library(ggplot2)data <- read_dta("C:/Users/attef/OneDrive/Documents/Replicaproject/Replica/analysis/data/analysis_data.dta")df <- as.data.table(haven::read_dta("C:/Users/attef/OneDrive/Documents/Replicaproject/Replica/analysis/data/analysis_data.dta"))# Filter for Retailer Aretailer_A <- df_hourly[website == "A"]ggplot(retailer_A, aes(x = hourofweek, y = hourly_dist)) + geom_line(color = "black", linewidth = 1) + # X-axis: tick every 24 hours (no labels) scale_x_continuous( breaks = seq(0, 168, by = 24), limits = c(0, 168), expand = c(0, 0) ) + # Y-axis: 0% to 1% for Retailer A scale_y_continuous( limits = c(0, 1), breaks = seq(0, 1, by = 0.2), labels = function(x) sprintf("%.1f", x) ) + # Vertical dashed lines at day boundaries geom_vline(xintercept = seq(24, 144, by = 24), linetype = "dashed", color = "gray60") + # Add day labels as text (not tick labels) annotate("text", x = 12, y = 0, label = "Sat", vjust = 1.5, size = 4) + annotate("text", x = 36, y = 0, label = "Sun", vjust = 1.5, size = 4) + annotate("text", x = 60, y = 0, label = "Mon", vjust = 1.5, size = 4) + annotate("text", x = 84, y = 0, label = "Tue", vjust = 1.5, size = 4) + annotate("text", x = 108, y = 0, label = "Wed", vjust = 1.5, size = 4) + annotate("text", x = 132, y = 0, label = "Thu", vjust = 1.5, size = 4) + annotate("text", x = 156, y = 0, label = "Fri", vjust = 1.5, size = 4) + labs( title = "Panel A. Retailer A", x = "Hour of Week", y = "Percent of Price Changes" ) + theme_minimal(base_size = 14) + theme( panel.grid.minor = element_blank(), axis.text.x = element_blank(), # Hide tick labels axis.ticks.x = element_blank(), plot.title = element_text(hjust = 0.5) )ggplot(df_hourly[website == "B"], aes(x = hourofweek, y = hourly_dist)) + geom_line(color = "black", linewidth = 1) + scale_x_continuous( breaks = seq(0, 168, by = 24), limits = c(0, 168), expand = c(0, 0) ) + scale_y_continuous( limits = c(0, 1), breaks = seq(0, 1, by = 0.2), labels = function(x) sprintf("%.1f", x) ) + geom_vline(xintercept = seq(24, 144, by = 24), linetype = "dashed", color = "gray60") + annotate("text", x = seq(12, 156, by = 24), y = 0, label = c("Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri"), vjust = 1.5, size = 4) + labs( title = "Panel B. Retailer B", x = "Hour of Week", y = "Percent of Price Changes" ) + theme_minimal(base_size = 14) + theme( axis.text.x = element_blank(), axis.ticks.x = element_blank(), axis.text.y = element_text(size = 10), plot.title = element_text(hjust = 0.5), )ggplot(df_hourly[website == "C"], aes(x = hourofweek, y = hourly_dist)) + geom_line(color = "black", linewidth = 1) + scale_x_continuous( breaks = seq(0, 168, by = 24), limits = c(0, 168), expand = c(0, 0) ) + scale_y_continuous( limits = c(0, 8), breaks = seq(0, 8, by = 2), labels = function(x) sprintf("%.0f", x) ) + geom_vline(xintercept = seq(24, 144, by = 24), linetype = "dashed", color = "gray60") + annotate("text", x = seq(12, 156, by = 24), y = 0, label = c("Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri"), vjust = 1.5, size = 4) + labs( title = "Panel C. Retailer C", x = "Hour of Week", y = "Percent of Price Changes" ) + theme_minimal(base_size = 14) + theme( axis.text.x = element_blank(), axis.ticks.x = element_blank(), axis.text.y = element_text(size = 10), plot.title = element_text(hjust = 0.5), )ggplot(df_hourly[website == "D"], aes(x = hourofweek, y = hourly_dist)) + geom_line(color = "black", linewidth = 1) + scale_x_continuous( breaks = seq(0, 168, by = 24), limits = c(0, 168), expand = c(0, 0) ) + scale_y_continuous( limits = c(0, 25), breaks = seq(0, 25, by = 5), labels = function(x) sprintf("%.0f", x) ) + geom_vline(xintercept = seq(24, 144, by = 24), linetype = "dashed", color = "gray60") + annotate("text", x = seq(12, 156, by = 24), y = 0, label = c("Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri"), vjust = 1.5, size = 4) + labs( title = "Panel D. Retailer D", x = "Hour of Week", y = "Percent of Price Changes" ) + theme_minimal(base_size = 14) + theme( axis.text.x = element_blank(), axis.ticks.x = element_blank(), axis.text.y = element_text(size = 10), plot.title = element_text(hjust = 0.5), )ggplot(df_hourly[website == "E"], aes(x = hourofweek, y = hourly_dist)) + geom_line(color = "black", linewidth = 1) + scale_x_continuous( breaks = seq(0, 168, by = 24), limits = c(0, 168), expand = c(0, 0) ) + scale_y_continuous( limits = c(0, 60), breaks = seq(0, 60, by = 10), labels = function(x) sprintf("%.0f", x) ) + geom_vline(xintercept = seq(24, 144, by = 24), linetype = "dashed", color = "gray60") + annotate("text", x = seq(12, 156, by = 24), y = 0, label = c("Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri"), vjust = 1.5, size = 4) + labs( title = "Panel E. Retailer E", x = "Hour of Week", y = "Percent of Price Changes" ) + theme_minimal(base_size = 14) + theme( axis.text.x = element_blank(), axis.ticks.x = element_blank(), axis.text.y = element_text(size = 10), plot.title = element_text(hjust = 0.5), )
First Graph
Second Graph
Third Graph
Fourth Graph
Fifth Graph
References
Brown, Z. Y., & MacKay, A. (2023). Competition in pricing algorithms. The Quarterly Journal of Economics, 138(1), 113–157. https://doi.org/10.1093/qje/qjac035
Posit, PBC. (2022). Quarto: Scientific and technical publishing system. https://quarto.org