__STYLES__
The goal of this analysis is to evaluate the performance of three marketing campaigns based on weekly sales data and determine which campaign performed the best. The dataset includes sales data aggregated by LocationID
, PromotionID
, and week.
I extracted the dataset used for this analysis using this SQL code
SELECT * FROM tc-da-1.turing_data_analytics.wa_marketing_campaign;
The dataset includes the following columns:
MarketID
: Unique identifier for the marketMarketSize
: Size of the market areaLocationID
: Unique identifier for the store locationAgeOfStore
: Age of the store in yearsPromotion
: Identifier for the promotion (1, 2, or 3)Week
: Week number when the promotion was runSalesInThousands
: Sales amount to thousands of dollars-- Calculate stats for Promotion 1
WITH promo_1 AS (
SELECT
location_id,
AVG(sales_in_thousands) AS avg_sales
FROM
`tc-da-1.turing_data_analytics.wa_marketing_campaign`
WHERE Promotion = 1
GROUP BY location_id
),
stats_1 AS (
SELECT
AVG(avg_sales) AS mean_sales,
VARIANCE(avg_sales) AS var_sales,
COUNT(location_id) AS n_count
FROM promo_1
)
-- Calculate stats for Promotion 2
, promo_2 AS (
SELECT
location_id,
AVG(sales_in_thousands) AS avg_sales
FROM
`tc-da-1.turing_data_analytics.wa_marketing_campaign`
WHERE Promotion = 2
GROUP BY location_id
),
stats_2 AS (
SELECT
AVG(avg_sales) AS mean_sales,
VARIANCE(avg_sales) AS var_sales,
COUNT(location_id) AS n_count
FROM promo_2
)
-- Calculate stats for Promotion 3
, promo_3 AS (
SELECT
location_id,
AVG(sales_in_thousands) AS avg_sales
FROM
`tc-da-1.turing_data_analytics.wa_marketing_campaign`
WHERE Promotion = 3
GROUP BY location_id
),
stats_3 AS (
SELECT
AVG(avg_sales) AS mean_sales,
VARIANCE(avg_sales) AS var_sales,
COUNT(location_id) AS n_count
FROM promo_3
)
-- Combine the results into a single output
SELECT
'Promotion 1' AS Promotion, mean_sales, var_sales, n_count
FROM stats_1
UNION ALL
SELECT
'Promotion 2' AS Promotion, mean_sales, var_sales, n_count
FROM stats_2
UNION ALL
SELECT
'Promotion 3' AS Promotion, mean_sales, var_sales, n_count
FROM stats_3;
# Filter data for each promotion
campaign_1 = agg_df[agg_df['Promotion'] == 1]['SalesInThousands']
campaign_2 = agg_df[agg_df['Promotion'] == 2]['SalesInThousands']
campaign_3 = agg_df[agg_df['Promotion'] == 3]['SalesInThousands']
# T-test between Campaign 1 and Campaign 2
t_stat, p_value = stats.ttest_ind(campaign_1, campaign_2)
print(f"Campaign 1 vs Campaign 2: T-stat = {t_stat}, P-value = {p_value}")
# T-test between Campaign 1 and Campaign 3
t_stat, p_value = stats.ttest_ind(campaign_1, campaign_3)
print(f"Campaign 1 vs Campaign 3: T-stat = {t_stat}, P-value = {p_value}")
# T-test between Campaign 2 and Campaign 3
t_stat, p_value = stats.ttest_ind(campaign_2, campaign_3)
print(f"Campaign 2 vs Campaign 3: T-stat = {t_stat}, P-value = {p_value}")
Results:
Interpretation:
from statsmodels.stats.multitest import multipletests
# Correct for multiple testing using Bonferroni correction
corrected_pvals = multipletests(p_values, alpha=0.01, method='bonferroni')[1]
# Output the results in a DataFrame
results = pd.DataFrame({
'Comparison': combinations,
'Original p-value': p_values,
'Corrected p-value': corrected_pvals
})
# Print the results
print("\nCorrected Pairwise Comparison Results:")
print(results)
The following are the corrected p-values:
Comparison Original p-value Corrected p-value
Only the comparison between Promo 2 vs Promo 1 remained statistically significant after applying the correction.
df_agg = df.groupby(['LocationID', 'Promotion']).agg(
{'SalesInThousands': 'mean'}
).reset_index()
def confidence_interval(data1, data2, confidence=0.99):
diff_means = data1.mean() - data2.mean()
se = np.sqrt(data1.var()/len(data1) + data2.var()/len(data2))
margin_of_error = se * stats.t.ppf((1 + confidence) / 2., len(data1) + len(data2) - 2)
return diff_means - margin_of_error, diff_means + margin_of_error
ci_1_2 = confidence_interval(campaign_1, campaign_2)
ci_1_3 = confidence_interval(campaign_1, campaign_3)
ci_2_3 = confidence_interval(campaign_2, campaign_3)
def confidence_interval(data1, data2, confidence=0.99):
diff_means = data1.mean() - data2.mean()
se = np.sqrt(data1.var()/len(data1) + data2.var()/len(data2))
margin_of_error = se * stats.t.ppf((1 + confidence) / 2., len(data1) + len(data2) - 2)
return diff_means - margin_of_error, diff_means + margin_of_error
# Filter data for each promotion
campaign_1 = df_agg[df_agg['Promotion'] == 1]['SalesInThousands']
campaign_2 = df_agg[df_agg['Promotion'] == 2]['SalesInThousands']
campaign_3 = df_agg[df_agg['Promotion'] == 3]['SalesInThousands']
# Calculate confidence intervals
ci_1_2 = confidence_interval(campaign_1, campaign_2)
ci_1_3 = confidence_interval(campaign_1, campaign_3)
ci_2_3 = confidence_interval(campaign_2, campaign_3)
print(f"Confidence Interval for Campaign 1 vs Campaign 2: {ci_1_2}")
print(f"Confidence Interval for Campaign 1 vs Campaign 3: {ci_1_3}")
print(f"Confidence Interval for Campaign 2 vs Campaign 3: {ci_2_3}")
This A/B test analysis provides clear evidence that Promotion 1 is the most effective campaign. While Promotion 3 performs similarly to Promotion 1 in small and large markets, its underperformance in medium-sized markets is a concern that requires further exploration. Promotion 2 was the least effective, and its discontinuation is advised. This comprehensive analysis and robust statistical evaluation provide actionable insights for optimizing marketing strategies.
Here is the link to the python sheet used https://drive.google.com/file/d/1h-tTuOouINHCQRZf9UIN6ZIbLG6BiFCR/view?usp=sharing
This comprehensive analysis and robust statistical evaluation provide actionable insights for optimizing marketing strategies.