Prerequisite Code & Setup
Setting global defaults for code chunks
knitr::opts_chunk$set(
comment = '', fig.width = 6, fig.height = 6,
warning = FALSE, error = FALSE, message = FALSE,
include = TRUE, echo = TRUE, strip.white = TRUE,
tidy = TRUE, highlight = TRUE
)
Loading libraries and data
libraries <- c("tidyverse","completejourney","lubridate","gridExtra","ggridges","naniar", "RColorBrewer", "hexbin")
# Load multiple packages
lapply(libraries, require, character.only = TRUE)
# Full complete journey dataset... because slow loading is cool
promotions <- get_promotions()
transactions <- get_transactions()
dim(promotions)
dim(demographics)
dim(campaigns)
dim(campaign_descriptions)
Creating Visualizations
str(promotions)
str(demographics)
str(campaign_descriptions)
str(campaigns)
intersect(colnames(campaigns),colnames(demographics))
intersect(colnames(campaign_descriptions),colnames(campaigns))
data_clean <- demographics %>%
inner_join(campaigns, by = "household_id") %>%
inner_join(campaign_descriptions, by = "campaign_id") %>%
mutate(camp_length = as.duration(end_date - start_date))
# Range of dates, number of NA's
data_clean %>%
summarize(max_date = max(end_date),
min_date = min(start_date),
nas = sum(is.na(data_clean)))
p1 <- data_clean %>%
group_by(income) %>%
summarize( mean_days = (mean(camp_length/86400))) %>%
arrange(desc(mean_days)) %>%
ggplot(aes(x = reorder(income, -mean_days), y = mean_days,
fill = reorder(income, -mean_days))) +
geom_bar(stat = "identity", show.legend = FALSE) +
scale_y_continuous() +
scale_fill_grey() +
labs(title = "Mean Length (Days) of Marketing Campaigns by Income Group",
subtitle =
"Households with income under 15k see the longest avg. campaign times.",
caption = "Based off the CompleteJourney data set by Brad Boehmke",
x = "Household Income Group",
y = "Avg. Length of Campaign"
)
p2 <- data_clean %>%
filter(income == "Under 15K") %>%
group_by(campaign_type) %>%
ggplot(aes(x = campaign_type, y = (camp_length)/86400,
fill = campaign_type)) +
geom_violin() +
scale_fill_brewer(type = "qual", palette = "Set2",
name = "Campaign Type") +
geom_jitter(stat = "identity", width = 0.07,
color = "black", alpha = 0.25) +
labs(title = "Campaign Length By Campaign Type for Houses with Income Less Than $15k",
subtitle = "Drilling down into campaigns for houses with income less than 15K, campaign type C has the longest typical campaign time hovering \n between 60-80 days per campaign. Additionally, campaigns A and B occur more often than Campaign C (higher frequency), but \n they have lower typical durations in days",
x = "Campaign Type",
y = "Length of Campaign (days)")
data_bigger <- data_clean %>%
inner_join(transactions, by = "household_id") %>%
inner_join(products, by = "product_id") %>%
filter(campaign_type == "Type C") %>%
select(product_id, product_type, quantity, camp_length) %>%
group_by(product_id, product_type) %>%
summarize(med_qty = median(quantity, na.rm = TRUE),
med_length = median(as.numeric(camp_length/86400), na.rm = TRUE)) %>%
filter(med_qty > 0) %>%
arrange(desc(med_qty))
qty_mn <- mean(data_bigger$med_qty, na.rm = TRUE)
qty_sd <- sd(data_bigger$med_qty, na.rm = TRUE)
LOT_mn <- mean(data_bigger$med_length, na.rm = TRUE)
LOT_sd <- sd(data_bigger$med_length, na.rm = TRUE)
p3 <- data_bigger %>%
filter(med_qty <= qty_mn + 3*qty_sd & med_qty >= qty_mn - 3*qty_sd) %>%
group_by(product_id) %>%
arrange(desc(med_qty)) %>%
ggplot(aes(x = med_length, y = med_qty)) +
geom_hex(bins = 15, show.legend = FALSE) +
viridis::scale_fill_viridis(option = "E", alpha = 0.8) +
labs(title = "Median Quantity Sold Compared to Median Length of a Campaign Type C by Product_id",
subtitle = "Most C-Type Campaigns run for 50-60 days, with the typical product that campaign C applies to being sold in \n quantities of 1-5 units per transaction. In other words, Campaign C often runs for 50-60 days on low-quantity items.",
x = "Median Length of Campaign Time (days) by Product",
y = "Median Quantity Sold per Transaction by Product",
)
Visualization Outputs
p1

p2

p3

LS0tDQp0aXRsZTogIkxhYiA1IC0gVmlzdWFsaXphdGlvbnMiDQphdXRob3I6ICJSb2FuIFphcHBhbnRpIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KIyMjIFByZXJlcXVpc2l0ZSBDb2RlICYgU2V0dXANClNldHRpbmcgZ2xvYmFsIGRlZmF1bHRzIGZvciBjb2RlIGNodW5rcw0KYGBge3IgR2xvYmFsIFNldHVwLCBzZXR1cCwgaW5jbHVkZT1UUlVFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KA0KICBjb21tZW50ID0gJycsIGZpZy53aWR0aCA9IDYsIGZpZy5oZWlnaHQgPSA2LA0KICB3YXJuaW5nID0gRkFMU0UsIGVycm9yID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwNCiAgaW5jbHVkZSA9IFRSVUUsIGVjaG8gPSBUUlVFLCBzdHJpcC53aGl0ZSA9IFRSVUUsDQogIHRpZHkgPSBUUlVFLCBoaWdobGlnaHQgPSBUUlVFDQopDQpgYGANCg0KTG9hZGluZyBsaWJyYXJpZXMgYW5kIGRhdGENCmBgYHtyIERhdGEsIGVjaG8gPSBUUlVFLCByZXN1bHRzID0gRkFMU0V9DQpsaWJyYXJpZXMgPC0gYygidGlkeXZlcnNlIiwiY29tcGxldGVqb3VybmV5IiwibHVicmlkYXRlIiwiZ3JpZEV4dHJhIiwiZ2dyaWRnZXMiLCJuYW5pYXIiLCAiUkNvbG9yQnJld2VyIiwgImhleGJpbiIpDQoNCiMgTG9hZCBtdWx0aXBsZSBwYWNrYWdlcw0KbGFwcGx5KGxpYnJhcmllcywgcmVxdWlyZSwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKSAgICANCg0KIyBGdWxsIGNvbXBsZXRlIGpvdXJuZXkgZGF0YXNldC4uLiBiZWNhdXNlIHNsb3cgbG9hZGluZyBpcyBjb29sDQpwcm9tb3Rpb25zIDwtIGdldF9wcm9tb3Rpb25zKCkNCnRyYW5zYWN0aW9ucyA8LSBnZXRfdHJhbnNhY3Rpb25zKCkNCg0KZGltKHByb21vdGlvbnMpDQpkaW0oZGVtb2dyYXBoaWNzKQ0KZGltKGNhbXBhaWducykNCmRpbShjYW1wYWlnbl9kZXNjcmlwdGlvbnMpDQpgYGANCiAgDQoNCiMjIyBDcmVhdGluZyBWaXN1YWxpemF0aW9ucw0KDQpgYGB7ciBVbmRlcnN0YW5kaW5nIFRhYmxlcywgZWNobyA9IFRSVUUsIHJlc3VsdHMgPSBGQUxTRX0NCnN0cihwcm9tb3Rpb25zKQ0Kc3RyKGRlbW9ncmFwaGljcykNCnN0cihjYW1wYWlnbl9kZXNjcmlwdGlvbnMpDQpzdHIoY2FtcGFpZ25zKQ0KDQppbnRlcnNlY3QoY29sbmFtZXMoY2FtcGFpZ25zKSxjb2xuYW1lcyhkZW1vZ3JhcGhpY3MpKQ0KaW50ZXJzZWN0KGNvbG5hbWVzKGNhbXBhaWduX2Rlc2NyaXB0aW9ucyksY29sbmFtZXMoY2FtcGFpZ25zKSkNCmBgYA0KDQoNCmBgYHtyIENyZWF0aW5nIERhdGEgRnJhbWUsIGVjaG8gPSBUUlVFLCByZXN1bHRzID0gRkFMU0V9DQoNCmRhdGFfY2xlYW4gPC0gZGVtb2dyYXBoaWNzICU+JSANCiAgaW5uZXJfam9pbihjYW1wYWlnbnMsIGJ5ID0gImhvdXNlaG9sZF9pZCIpICU+JSANCiAgaW5uZXJfam9pbihjYW1wYWlnbl9kZXNjcmlwdGlvbnMsIGJ5ID0gImNhbXBhaWduX2lkIikgJT4lDQogIG11dGF0ZShjYW1wX2xlbmd0aCA9IGFzLmR1cmF0aW9uKGVuZF9kYXRlIC0gc3RhcnRfZGF0ZSkpDQoNCiMgUmFuZ2Ugb2YgZGF0ZXMsIG51bWJlciBvZiBOQSdzDQpkYXRhX2NsZWFuICU+JSANCiAgc3VtbWFyaXplKG1heF9kYXRlID0gbWF4KGVuZF9kYXRlKSwNCiAgICAgICAgICAgIG1pbl9kYXRlID0gbWluKHN0YXJ0X2RhdGUpLA0KICAgICAgICAgICAgbmFzID0gc3VtKGlzLm5hKGRhdGFfY2xlYW4pKSkNCmBgYA0KDQpgYGB7ciBGaXJzdCBBbmFseXNpcyBHcmFwaCwgZWNobyA9IFRSVUUsIHJlc3VsdHMgPSBGQUxTRX0NCnAxIDwtIGRhdGFfY2xlYW4gJT4lDQogIGdyb3VwX2J5KGluY29tZSkgJT4lIA0KICBzdW1tYXJpemUoIG1lYW5fZGF5cyA9IChtZWFuKGNhbXBfbGVuZ3RoLzg2NDAwKSkpICU+JSANCiAgYXJyYW5nZShkZXNjKG1lYW5fZGF5cykpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gcmVvcmRlcihpbmNvbWUsIC1tZWFuX2RheXMpLCB5ID0gbWVhbl9kYXlzLCANCiAgICAgICAgICAgICBmaWxsID0gcmVvcmRlcihpbmNvbWUsIC1tZWFuX2RheXMpKSkgKw0KICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKCkgKw0KICAgIHNjYWxlX2ZpbGxfZ3JleSgpICsNCiAgICBsYWJzKHRpdGxlID0gIk1lYW4gTGVuZ3RoIChEYXlzKSBvZiBNYXJrZXRpbmcgQ2FtcGFpZ25zIGJ5IEluY29tZSBHcm91cCIsDQogICAgICAgICBzdWJ0aXRsZSA9IA0KICAgICAgICAiSG91c2Vob2xkcyB3aXRoIGluY29tZSB1bmRlciAxNWsgc2VlIHRoZSBsb25nZXN0IGF2Zy4gY2FtcGFpZ24gdGltZXMuIiwNCiAgICAgICAgIGNhcHRpb24gPSAiQmFzZWQgb2ZmIHRoZSBDb21wbGV0ZUpvdXJuZXkgZGF0YSBzZXQgYnkgQnJhZCBCb2VobWtlIiwNCiAgICAgICAgeCA9ICJIb3VzZWhvbGQgSW5jb21lIEdyb3VwIiwNCiAgICAgICAgeSA9ICJBdmcuIExlbmd0aCBvZiBDYW1wYWlnbiINCiAgICApDQoNCmBgYA0KDQpgYGB7ciBTZWNvbmQgQW5hbHlzaXMgR3JhcGgsIHJlc3VsdHMgPSBGQUxTRSwgZWNobyA9IFRSVUV9DQpwMiA8LSBkYXRhX2NsZWFuICU+JSANCiAgZmlsdGVyKGluY29tZSA9PSAiVW5kZXIgMTVLIikgJT4lIA0KICBncm91cF9ieShjYW1wYWlnbl90eXBlKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gY2FtcGFpZ25fdHlwZSwgeSA9IChjYW1wX2xlbmd0aCkvODY0MDAsIA0KICAgICAgICAgICAgIGZpbGwgPSBjYW1wYWlnbl90eXBlKSkgKw0KICAgIGdlb21fdmlvbGluKCkgKw0KICAgIHNjYWxlX2ZpbGxfYnJld2VyKHR5cGUgPSAicXVhbCIsIHBhbGV0dGUgPSAiU2V0MiIsDQogICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJDYW1wYWlnbiBUeXBlIikgKw0KICBnZW9tX2ppdHRlcihzdGF0ID0gImlkZW50aXR5Iiwgd2lkdGggPSAwLjA3LCANCiAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuMjUpICsNCiAgbGFicyh0aXRsZSA9ICJDYW1wYWlnbiBMZW5ndGggQnkgQ2FtcGFpZ24gVHlwZSBmb3IgSG91c2VzIHdpdGggSW5jb21lIExlc3MgVGhhbiAkMTVrIiwNCiAgICAgICBzdWJ0aXRsZSA9ICJEcmlsbGluZyBkb3duIGludG8gY2FtcGFpZ25zIGZvciBob3VzZXMgd2l0aCBpbmNvbWUgbGVzcyB0aGFuIDE1SywgY2FtcGFpZ24gdHlwZSBDIGhhcyB0aGUgbG9uZ2VzdCB0eXBpY2FsIGNhbXBhaWduIHRpbWUgaG92ZXJpbmcgXG4gYmV0d2VlbiA2MC04MCBkYXlzIHBlciBjYW1wYWlnbi4gQWRkaXRpb25hbGx5LCBjYW1wYWlnbnMgQSBhbmQgQiBvY2N1ciBtb3JlIG9mdGVuIHRoYW4gQ2FtcGFpZ24gQyAoaGlnaGVyIGZyZXF1ZW5jeSksIGJ1dCBcbiB0aGV5IGhhdmUgbG93ZXIgdHlwaWNhbCBkdXJhdGlvbnMgaW4gZGF5cyIsDQogICAgICAgeCA9ICJDYW1wYWlnbiBUeXBlIiwNCiAgICAgICB5ID0gIkxlbmd0aCBvZiBDYW1wYWlnbiAoZGF5cykiKQ0KDQpgYGANCg0KYGBge3IgVGhpcmQgQW5hbHlzaXMgR3JhcGgsIGVjaG8gPSBUUlVFLCByZXN1bHRzID0gRkFMU0V9DQoNCg0KZGF0YV9iaWdnZXIgPC0gZGF0YV9jbGVhbiAlPiUgDQogIGlubmVyX2pvaW4odHJhbnNhY3Rpb25zLCBieSA9ICJob3VzZWhvbGRfaWQiKSAlPiUgDQogIGlubmVyX2pvaW4ocHJvZHVjdHMsIGJ5ID0gInByb2R1Y3RfaWQiKSAlPiUgDQogIGZpbHRlcihjYW1wYWlnbl90eXBlID09ICJUeXBlIEMiKSAlPiUgDQogIHNlbGVjdChwcm9kdWN0X2lkLCBwcm9kdWN0X3R5cGUsIHF1YW50aXR5LCBjYW1wX2xlbmd0aCkgJT4lIA0KICBncm91cF9ieShwcm9kdWN0X2lkLCBwcm9kdWN0X3R5cGUpICU+JSANCiAgc3VtbWFyaXplKG1lZF9xdHkgPSBtZWRpYW4ocXVhbnRpdHksIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICBtZWRfbGVuZ3RoID0gbWVkaWFuKGFzLm51bWVyaWMoY2FtcF9sZW5ndGgvODY0MDApLCBuYS5ybSA9IFRSVUUpKSAlPiUNCiAgZmlsdGVyKG1lZF9xdHkgPiAwKSAlPiUgDQogIGFycmFuZ2UoZGVzYyhtZWRfcXR5KSkNCg0KcXR5X21uIDwtIG1lYW4oZGF0YV9iaWdnZXIkbWVkX3F0eSwgbmEucm0gPSBUUlVFKQ0KcXR5X3NkIDwtIHNkKGRhdGFfYmlnZ2VyJG1lZF9xdHksIG5hLnJtID0gVFJVRSkNCg0KTE9UX21uIDwtIG1lYW4oZGF0YV9iaWdnZXIkbWVkX2xlbmd0aCwgbmEucm0gPSBUUlVFKQ0KTE9UX3NkIDwtIHNkKGRhdGFfYmlnZ2VyJG1lZF9sZW5ndGgsIG5hLnJtID0gVFJVRSkNCg0KcDMgPC0gZGF0YV9iaWdnZXIgJT4lIA0KICBmaWx0ZXIobWVkX3F0eSA8PSBxdHlfbW4gKyAzKnF0eV9zZCAmIG1lZF9xdHkgPj0gcXR5X21uIC0gMypxdHlfc2QpICU+JSANCiAgZ3JvdXBfYnkocHJvZHVjdF9pZCkgJT4lIA0KICBhcnJhbmdlKGRlc2MobWVkX3F0eSkpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gbWVkX2xlbmd0aCwgeSA9IG1lZF9xdHkpKSArIA0KICAgZ2VvbV9oZXgoYmlucyA9IDE1LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogICB2aXJpZGlzOjpzY2FsZV9maWxsX3ZpcmlkaXMob3B0aW9uID0gIkUiLCBhbHBoYSA9IDAuOCkgKw0KICBsYWJzKHRpdGxlID0gIk1lZGlhbiBRdWFudGl0eSBTb2xkIENvbXBhcmVkIHRvIE1lZGlhbiBMZW5ndGggb2YgYSBDYW1wYWlnbiBUeXBlIEMgYnkgUHJvZHVjdF9pZCIsDQogICAgICAgc3VidGl0bGUgPSAiTW9zdCBDLVR5cGUgQ2FtcGFpZ25zIHJ1biBmb3IgNTAtNjAgZGF5cywgd2l0aCB0aGUgdHlwaWNhbCBwcm9kdWN0IHRoYXQgY2FtcGFpZ24gQyBhcHBsaWVzIHRvIGJlaW5nIHNvbGQgaW4gXG4gcXVhbnRpdGllcyBvZiAxLTUgdW5pdHMgcGVyIHRyYW5zYWN0aW9uLiBJbiBvdGhlciB3b3JkcywgQ2FtcGFpZ24gQyBvZnRlbiBydW5zIGZvciA1MC02MCBkYXlzIG9uIGxvdy1xdWFudGl0eSBpdGVtcy4iLA0KICAgICAgIHggPSAiTWVkaWFuIExlbmd0aCBvZiBDYW1wYWlnbiBUaW1lIChkYXlzKSBieSBQcm9kdWN0IiwNCiAgICAgICB5ID0gIk1lZGlhbiBRdWFudGl0eSBTb2xkIHBlciBUcmFuc2FjdGlvbiBieSBQcm9kdWN0IiwNCiAgKQ0KDQpgYGANCg0KIyMjIFZpc3VhbGl6YXRpb24gT3V0cHV0cyAgDQpgYGB7ciBHcmFwaCBPdXRwdXRzLCBmaWcuYWxpZ249ICdjZW50ZXInLCBmaWcud2lkdGggPSA5LjUsIGZpZy5oZWlnaHQgPSA5LjV9DQpwMQ0KDQpwMg0KDQpwMw0KYGBgDQoNCg0K