head(df)
## CustomerID Age Gender Device Channel Ad_Spend Clicks Purchases Revenue
## 1 1 54 M Mobile Social 718.60 95 6 149.16
## 2 2 18 F Mobile Search 233.00 34 1 22.22
## 3 3 42 F Mobile Search 122.51 18 0 0.00
## 4 4 27 F Desktop Social 198.78 19 1 13.22
## 5 5 53 F Mobile Social 145.19 19 4 150.48
## 6 6 35 M Desktop Video 125.74 9 0 0.00
nrow(df)
## [1] 1000
Answer: There are 1,000 rows, one per customer: each
row records who the customer is (Age, Gender,
Device), which ad channel reached them
(Channel), what was spent on them (Ad_Spend),
and how they responded (Clicks, Purchases,
Revenue). Gender, Device, and
Channel are categorical; the rest are numeric
(CustomerID is just an identifier).
summary(df)
## CustomerID Age Gender Device
## Min. : 1.0 Min. :18.00 Length :1000 Length :1000
## 1st Qu.: 250.8 1st Qu.:31.00 N.unique : 2 N.unique : 2
## Median : 500.5 Median :43.00 N.blank : 0 N.blank : 0
## Mean : 500.5 Mean :42.51 Min.nchar: 1 Min.nchar: 6
## 3rd Qu.: 750.2 3rd Qu.:54.00 Max.nchar: 1 Max.nchar: 7
## Max. :1000.0 Max. :65.00
## Channel Ad_Spend Clicks Purchases
## Length :1000 Min. : 1.83 Min. : 0.00 Min. : 0.000
## N.unique : 5 1st Qu.: 96.86 1st Qu.: 10.00 1st Qu.: 0.000
## N.blank : 0 Median : 172.25 Median : 19.00 Median : 1.000
## Min.nchar: 5 Mean : 216.78 Mean : 24.17 Mean : 1.047
## Max.nchar: 7 3rd Qu.: 278.74 3rd Qu.: 32.00 3rd Qu.: 2.000
## Max. :3875.35 Max. :322.00 Max. :17.000
## Revenue
## Min. : 0.00
## 1st Qu.: 0.00
## Median : 26.86
## Mean : 41.21
## 3rd Qu.: 61.28
## Max. :702.61
Answer: No missing values in any column. For
Ad_Spend, the mean (216.8) is well above the median
(172.2). From the lecture: when the mean is pulled above the median, the
distribution is right-skewed; a minority of large
values drags the mean up while the median stays with the typical
customer.
ggplot(df, aes(Ad_Spend)) +
geom_histogram(bins = 30, fill = "steelblue", color = "white") +
geom_vline(aes(xintercept = mean(Ad_Spend)), linetype = "dashed") +
geom_vline(aes(xintercept = median(Ad_Spend))) +
labs(title = "Distribution of Ad Spend",
subtitle = "Dashed = mean, solid = median",
x = "Ad Spend ($)", y = "Count") +
theme_minimal()
Answer: Clearly right-skewed: most customers receive modest spend, with a long tail of customers receiving several times more. The dashed mean line sits visibly to the right of the solid median line, which is exactly the skew the summary statistics hinted at. A plausible marketing strategy behind this shape: the firm spends a baseline amount on most customers and concentrates extra budget on a small group it believes is high-value (retargeting, lookalike audiences, big-ticket prospects).
ggplot(df, aes(Ad_Spend)) +
geom_histogram(bins = 30, fill = "steelblue", color = "white") +
scale_x_continuous(trans = "log10") +
labs(title = "Distribution of Ad Spend (log scale)",
x = "Ad Spend ($, log10)", y = "Count") +
theme_minimal()
Answer: On the log scale the distribution becomes roughly symmetric and bell-shaped, so the “typical” customer is easy to read off: about $150–200. The low-spend customers, invisible in the left pile of the linear chart, are now spread out and visible. This is the lecture’s point about logs: they expand small values, compress large ones, and turn a skewed distribution into one you can actually read.
df %>%
count(Channel) %>%
mutate(p = n / sum(n)) %>%
ggplot(aes(reorder(Channel, -n), n)) +
geom_col(fill = "steelblue") +
geom_text(aes(label = percent(p, accuracy = 0.1)), vjust = -0.3, size = 3.5) +
labs(title = "Channel Mix", x = "Channel", y = "Customers") +
theme_minimal()
Answer: Not balanced. Search dominates (34.7%), followed by Social (22.7%), Display (19.4%), and Video (17.8%); Email is a distant last at 5.4%. The mix is plausible for an online retailer: search captures customers with existing intent, social and display do the prospecting, and email is cheap but only reaches customers the firm already knows.
ggplot(df, aes(y = Ad_Spend)) +
geom_boxplot(fill = "lightblue") +
scale_y_continuous(labels = dollar_format()) +
labs(title = "Boxplot of Ad Spend", y = "Ad Spend ($)") +
theme_minimal()
ggplot(df, aes(y = log(Ad_Spend + 1))) +
geom_boxplot(fill = "lightblue") +
labs(title = "Boxplot of Ad Spend (log scale)", y = "log Ad Spend") +
theme_minimal()
Answer: The 1.5 × IQR rule flags 39 customers, all on the high side; there are no low outliers on the raw scale. On the log scale the box is nearly symmetric and only a handful of extreme points remain flagged, telling us most of the “outliers” are just the natural tail of a skewed distribution rather than data errors. Should we drop them? Not without investigation: with 39 observations in 1,000, they can move averages. Best practice from the lecture: run any later analysis with and without them, disclose whatever we do, and prefer robust statistics (medians, quantiles) when describing spend.
Example: is ad spend targeted by device?
ggplot(df, aes(Device, Ad_Spend, fill = Device)) +
geom_boxplot(alpha = 0.7) +
scale_y_continuous(trans = "log10", labels = dollar_format()) +
labs(title = "Ad Spend by Device (log scale)",
x = NULL, y = "Ad Spend ($, log10)") +
theme_minimal() +
theme(legend.position = "none")
Answer: I asked whether Mobile and Desktop customers receive different ad spend. They essentially do not: the two distributions sit on top of each other (means 214 vs. 221, medians 175 vs. 170). Spend does not appear to be targeted by device in this data, even though mobile users are 65% of customers.