Dalam industri minuman berbasis kopi dan teh, peningkatan volume penjualan (sales) sering kali diperlakukan sebagai indikator utama keberhasilan bisnis. Namun, asumsi ini menyimpan risiko analitis yang serius: tingginya penjualan tidak selalu berbanding lurus dengan tingginya keuntungan. Suatu produk dapat mencetak volume penjualan besar namun sekaligus menggerus margin karena struktur biaya yang tidak efisien — fenomena yang kerap luput dari pengamatan apabila analisis hanya berhenti pada laporan penjualan agregat.
Dataset Coffee Chain menyimpan catatan transaksi dari sebuah jaringan kedai kopi yang beroperasi di empat wilayah pasar di Amerika Serikat: Central, East, South, dan West. Data ini mencakup informasi penjualan, biaya produksi (COGS), margin, pengeluaran pemasaran, serta profit aktual untuk 13 produk yang tersebar dalam empat kategori: Coffee, Espresso, Tea, dan Herbal Tea.
Laporan ini bertujuan untuk:
Berdasarkan eksplorasi awal data, laporan ini menguji hipotesis bahwa: margin (selisih antara harga jual dan harga pokok) memiliki pengaruh yang lebih dominan terhadap profit dibandingkan volume sales itu sendiri, dan bahwa terdapat kelompok produk maupun wilayah yang secara struktural beroperasi dengan profit negatif meski mencatatkan sales yang cukup besar.
Dataset Coffee Chain diperoleh dari SPADA UNS dalam format
.xlsx. Data mencakup 4.248 observasi
dengan 20 variabel, merepresentasikan catatan penjualan
periode 2012–2014 pada jaringan kedai kopi multiwilayah.
df_raw <- read_excel("Coffee Chain Datasets.xlsx")
# Rename kolom yang mengandung spasi agar compatible dengan sintaks R
df <- df_raw %>%
rename(
Area_Code = `Area Code`,
Market_Size = `Market Size`,
Product_Line = `Product Line`,
Product_Type = `Product Type`,
Budget_COGS = `Budget COGS`,
Budget_Margin = `Budget Margin`,
Budget_Profit = `Budget Profit`,
Budget_Sales = `Budget Sales`,
Total_Expenses = `Total Expenses`
)
# Pratinjau dimensi dan struktur data
cat("Dimensi data:", nrow(df), "baris x", ncol(df), "kolom\n\n")## Dimensi data: 4248 baris x 20 kolom
## Rows: 4,248
## Columns: 20
## $ Area_Code <dbl> 719, 970, 970, 303, 303, 720, 970, 719, 970, 719, 303, …
## $ Date <dttm> 2012-01-01, 2012-01-01, 2012-01-01, 2012-01-01, 2012-0…
## $ Market <chr> "Central", "Central", "Central", "Central", "Central", …
## $ Market_Size <chr> "Major Market", "Major Market", "Major Market", "Major …
## $ Product <chr> "Amaretto", "Colombian", "Decaf Irish Cream", "Green Te…
## $ Product_Line <chr> "Beans", "Beans", "Beans", "Leaves", "Beans", "Beans", …
## $ Product_Type <chr> "Coffee", "Coffee", "Coffee", "Tea", "Espresso", "Espre…
## $ State <chr> "Colorado", "Colorado", "Colorado", "Colorado", "Colora…
## $ Type <chr> "Regular", "Regular", "Decaf", "Regular", "Regular", "D…
## $ Budget_COGS <dbl> 90, 80, 100, 30, 60, 80, 140, 50, 50, 40, 50, 150, 100,…
## $ Budget_Margin <dbl> 130, 110, 140, 50, 90, 130, 160, 80, 70, 70, 70, 210, 1…
## $ Budget_Profit <dbl> 100, 80, 110, 30, 70, 80, 110, 20, 40, 20, 40, 130, 100…
## $ Budget_Sales <dbl> 220, 190, 240, 80, 150, 210, 300, 130, 120, 110, 120, 3…
## $ COGS <dbl> 89, 83, 95, 44, 54, 72, 170, 63, 60, 58, 64, 144, 95, 2…
## $ Inventory <dbl> 777, 623, 821, 623, 456, 558, 1091, 435, 336, 338, 965,…
## $ Margin <dbl> 130, 107, 139, 56, 80, 108, 171, 87, 80, 72, 76, 201, 1…
## $ Marketing <dbl> 24, 27, 26, 14, 15, 23, 47, 57, 19, 22, 19, 47, 30, 77,…
## $ Profit <dbl> 94, 68, 101, 30, 54, 53, 99, 0, 33, 17, 36, 111, 87, 20…
## $ Sales <dbl> 219, 190, 234, 100, 134, 180, 341, 150, 140, 130, 140, …
## $ Total_Expenses <dbl> 36, 39, 38, 26, 26, 55, 72, 87, 47, 55, 40, 90, 52, 109…
| Variabel | Deskripsi |
|---|---|
| Sales | Pendapatan kotor dari penjualan produk (USD) |
| Profit | Keuntungan bersih setelah dikurangi seluruh biaya (USD) |
| Margin | Selisih antara harga jual dan COGS (USD) |
| COGS | Cost of Goods Sold — biaya langsung produksi |
| Marketing | Biaya pemasaran per transaksi (USD) |
| Total Expenses | Total biaya operasional (Marketing + biaya lainnya) |
| Product Type | Kategori produk: Coffee, Espresso, Tea, Herbal Tea |
| Market | Wilayah pasar: Central, East, South, West |
| Market Size | Ukuran pasar: Major Market / Small Market |
df_clean <- df %>%
# Hapus spasi tersembunyi pada kolom karakter
mutate(across(where(is.character), str_trim)) %>%
# Feature engineering: variabel turunan yang kaya informasi
mutate(
# Profit Margin Rate: efisiensi konversi sales ke profit
Profit_Rate = Profit / Sales * 100,
# Expense Ratio: proporsi total biaya terhadap sales
Expense_Ratio = Total_Expenses / Sales * 100,
# Marketing Efficiency: profit yang dihasilkan per 1 unit marketing spend
Mktg_Efficiency = Profit / Marketing,
# Flag: apakah observasi menghasilkan profit negatif?
Loss_Flag = ifelse(Profit < 0, "Rugi", "Untung"),
# Margin Rate: margin sebagai % dari sales
Margin_Rate = Margin / Sales * 100
)
cat("Jumlah observasi dengan profit negatif:", sum(df_clean$Profit < 0), "\n")## Jumlah observasi dengan profit negatif: 528
## Proporsi rugi: 12.4 %
# Statistik deskriptif variabel numerik utama
df_clean %>%
select(Sales, Profit, Margin, COGS, Marketing, Total_Expenses, Profit_Rate) %>%
summary() %>%
kable(caption = "Statistik deskriptif variabel numerik utama")| Sales | Profit | Margin | COGS | Marketing | Total_Expenses | Profit_Rate | |
|---|---|---|---|---|---|---|---|
| Min. : 17 | Min. :-638.0 | Min. :-302.00 | Min. : 0.00 | Min. : 0.00 | Min. : 10.00 | Min. :-3190.00 | |
| 1st Qu.:100 | 1st Qu.: 17.0 | 1st Qu.: 52.75 | 1st Qu.: 43.00 | 1st Qu.: 13.00 | 1st Qu.: 33.00 | 1st Qu.: 16.09 | |
| Median :138 | Median : 40.0 | Median : 76.00 | Median : 60.00 | Median : 22.00 | Median : 46.00 | Median : 32.00 | |
| Mean :193 | Mean : 61.1 | Mean : 104.29 | Mean : 84.43 | Mean : 31.19 | Mean : 54.06 | Mean : 14.72 | |
| 3rd Qu.:230 | 3rd Qu.: 92.0 | 3rd Qu.: 132.00 | 3rd Qu.:100.00 | 3rd Qu.: 39.00 | 3rd Qu.: 65.00 | 3rd Qu.: 42.78 | |
| Max. :912 | Max. : 778.0 | Max. : 613.00 | Max. :364.00 | Max. :156.00 | Max. :190.00 | Max. : 118.08 |
Catatan interpretatif: Nilai minimum Profit sebesar -638 USD dan rata-rata Profit_Rate yang tidak homogen antar kelompok mengindikasikan adanya inefisiensi struktural pada segmen tertentu. Hal ini akan ditelaah lebih dalam pada bagian analisis.
profit_by_type <- df_clean %>%
group_by(Product_Type) %>%
summarise(
Total_Sales = sum(Sales),
Total_Profit = sum(Profit),
Avg_Profit_Rate = mean(Profit_Rate),
Pct_Loss = mean(Loss_Flag == "Rugi") * 100,
n = n(),
.groups = "drop"
) %>%
arrange(desc(Avg_Profit_Rate))
kable(profit_by_type %>%
mutate(across(where(is.numeric), ~round(., 2))),
caption = "Ringkasan profitabilitas per kategori produk")| Product_Type | Total_Sales | Total_Profit | Avg_Profit_Rate | Pct_Loss | n |
|---|---|---|---|---|---|
| Herbal Tea | 207214 | 63254 | 24.98 | 11.93 | 1056 |
| Coffee | 216828 | 74683 | 24.02 | 12.88 | 1056 |
| Espresso | 222996 | 68620 | 21.66 | 12.59 | 1176 |
| Tea | 172773 | 52986 | -15.31 | 12.29 | 960 |
profit_by_market <- df_clean %>%
group_by(Market) %>%
summarise(
Total_Sales = sum(Sales),
Total_Profit = sum(Profit),
Avg_Profit_Rate = mean(Profit_Rate),
Pct_Loss = mean(Loss_Flag == "Rugi") * 100,
.groups = "drop"
) %>%
arrange(desc(Avg_Profit_Rate))
kable(profit_by_market %>%
mutate(across(where(is.numeric), ~round(., 2))),
caption = "Ringkasan profitabilitas per wilayah pasar")| Market | Total_Sales | Total_Profit | Avg_Profit_Rate | Pct_Loss |
|---|---|---|---|---|
| Central | 265045 | 93852 | 30.43 | 10.27 |
| South | 103926 | 32478 | 27.19 | 11.01 |
| East | 178576 | 59217 | 17.19 | 15.09 |
| West | 272264 | 73996 | -8.87 | 13.54 |
Temuan awal yang krusial: Kategori Tea memiliki rata-rata Profit Rate sebesar -15.31% — artinya secara rata-rata setiap transaksi Tea justru menghabiskan uang, bukan menghasilkan. Demikian pula wilayah West dengan Profit Rate -8.87%. Ini adalah sinyal inefisiensi yang perlu pendalaman kuantitatif.
heatmap_data <- df_clean %>%
group_by(Product_Type, Market) %>%
summarise(Avg_Profit_Rate = mean(Profit_Rate), .groups = "drop")
ggplot(heatmap_data, aes(x = Market, y = Product_Type, fill = Avg_Profit_Rate)) +
geom_tile(color = "white", linewidth = 0.8) +
geom_text(aes(label = paste0(round(Avg_Profit_Rate, 1), "%")),
color = "white", fontface = "bold", size = 4.5) +
scale_fill_gradient2(
low = "#c0392b",
mid = "#f39c12",
high = "#27ae60",
midpoint = 0,
name = "Profit Rate (%)"
) +
labs(
title = "Rata-rata Profit Rate per Kombinasi Kategori Produk dan Wilayah Pasar",
subtitle = "Merah = profit negatif (rugi) | Hijau = profit positif",
x = "Wilayah Pasar",
y = "Kategori Produk",
caption = "Sumber: Coffee Chain Dataset"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold", size = 13),
plot.subtitle = element_text(color = "grey40"),
legend.position = "right"
)Interpretasi: Heatmap ini mengungkapkan pola yang tidak terlihat dari laporan agregat biasa. Kombinasi yang paling mengkhawatirkan adalah Tea di West (-98.3%) — artinya setiap transaksi Tea di wilayah West rata-rata menghasilkan kerugian hampir setara nilai penjualannya sendiri. Satu-satunya kombinasi lain yang merugi adalah Espresso di East (-26.1%). Di sisi positif, Coffee di East (46.6%) dan Tea di East (46.5%) adalah dua kombinasi paling menguntungkan, diikuti Espresso di Central (40.1%). Temuan ini menunjukkan bahwa masalah profitabilitas bersifat spesifik segmen, tidak merata — dan wilayah West pada kategori Tea memerlukan perhatian manajerial segera.
df_clean %>%
group_by(Product, Product_Type) %>%
summarise(
Avg_Sales = mean(Sales),
Avg_Profit = mean(Profit),
Avg_Rate = mean(Profit_Rate),
.groups = "drop"
) %>%
ggplot(aes(x = Avg_Sales, y = Avg_Profit, color = Product_Type, size = abs(Avg_Rate))) +
geom_point(alpha = 0.8) +
geom_hline(yintercept = 0, linetype = "dashed", color = "red", linewidth = 0.8) +
geom_vline(xintercept = mean(df_clean$Sales), linetype = "dotted", color = "grey40") +
geom_smooth(aes(group = 1), method = "lm", se = TRUE,
color = "steelblue", linetype = "dashed", linewidth = 0.7, alpha = 0.15) +
geom_text(aes(label = Product), size = 2.7, vjust = -1, hjust = 0.5, show.legend = FALSE) +
scale_color_manual(values = c("Coffee" = "#e67e22", "Espresso" = "#8e44ad",
"Tea" = "#27ae60", "Herbal Tea" = "#2980b9")) +
scale_size_continuous(range = c(2, 8), guide = "none") +
labs(
title = "Scatterplot Sales vs Profit per Produk",
subtitle = "Titik di bawah garis merah = produk yang secara rata-rata mengalami KERUGIAN",
x = "Rata-rata Sales (USD)",
y = "Rata-rata Profit (USD)",
color = "Kategori Produk",
caption = "Sumber: Coffee Chain Dataset | Ukuran titik ∝ |Profit Rate|"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold", size = 13),
plot.subtitle = element_text(color = "grey40"),
legend.position = "bottom"
)Interpretasi: Visualisasi ini membuktikan hipotesis utama: beberapa produk memiliki sales yang tidak rendah namun tetap menghasilkan profit negatif. Produk Earl Grey dan Lemon (kategori Tea dan Herbal Tea) berada di bawah garis merah — kondisi ini bukan sekadar kebetulan, melainkan mencerminkan struktur biaya yang bermasalah. Sementara itu, produk-produk Espresso seperti Caffe Mocha dan Regular Espresso konsisten berada di kuadran atas, mengonfirmasi bahwa kategori ini adalah cash cow perusahaan.
ggplot(df_clean, aes(x = reorder(Product_Type, Profit_Rate, FUN = median),
y = Profit_Rate, fill = Product_Type)) +
geom_violin(alpha = 0.6, trim = FALSE) +
geom_boxplot(width = 0.15, alpha = 0.9, outlier.size = 0.5) +
geom_hline(yintercept = 0, linetype = "dashed", color = "red", linewidth = 0.8) +
scale_fill_manual(values = c("Coffee" = "#e67e22", "Espresso" = "#8e44ad",
"Tea" = "#27ae60", "Herbal Tea" = "#2980b9")) +
coord_flip() +
labs(
title = "Distribusi Profit Rate per Kategori Produk",
subtitle = "Garis merah = titik impas (Profit Rate = 0%)",
x = "Kategori Produk",
y = "Profit Rate (%)",
fill = "Kategori",
caption = "Sumber: Coffee Chain Dataset"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold", size = 13),
plot.subtitle = element_text(color = "grey40"),
legend.position = "none"
)Interpretasi: Violin plot mengungkapkan tidak hanya perbedaan rata-rata, tetapi juga variabilitas profit rate antar kategori. Kategori Tea memiliki distribusi yang sangat lebar dan condong ke bawah garis merah, menandakan ketidakstabilan profitabilitas yang ekstrem. Espresso memiliki distribusi yang lebih padat di area positif, mencerminkan konsistensi kinerja yang baik. Coffee dan Herbal Tea menunjukkan pola bimodal — ada kelompok yang sangat menguntungkan dan ada yang justru merugi dalam kategori yang sama.
num_vars <- df_clean %>%
select(Sales, Profit, Margin, COGS, Marketing, Total_Expenses, Profit_Rate, Margin_Rate)
cor_matrix <- cor(num_vars, use = "complete.obs")
# Tampilkan sebagai tabel
kable(round(cor_matrix, 3),
caption = "Matriks korelasi Pearson antar variabel numerik")| Sales | Profit | Margin | COGS | Marketing | Total_Expenses | Profit_Rate | Margin_Rate | |
|---|---|---|---|---|---|---|---|---|
| Sales | 1.000 | 0.797 | 0.939 | 0.887 | 0.711 | 0.689 | 0.139 | 0.087 |
| Profit | 0.797 | 1.000 | 0.921 | 0.465 | 0.225 | 0.200 | 0.520 | 0.445 |
| Margin | 0.939 | 0.921 | 1.000 | 0.679 | 0.532 | 0.521 | 0.372 | 0.331 |
| COGS | 0.887 | 0.465 | 0.679 | 1.000 | 0.818 | 0.783 | -0.194 | -0.246 |
| Marketing | 0.711 | 0.225 | 0.532 | 0.818 | 1.000 | 0.966 | -0.251 | -0.247 |
| Total_Expenses | 0.689 | 0.200 | 0.521 | 0.783 | 0.966 | 1.000 | -0.252 | -0.235 |
| Profit_Rate | 0.139 | 0.520 | 0.372 | -0.194 | -0.251 | -0.252 | 1.000 | 0.973 |
| Margin_Rate | 0.087 | 0.445 | 0.331 | -0.246 | -0.247 | -0.235 | 0.973 | 1.000 |
# Visualisasi korelasi — pakai tidyr (sudah ada dalam tidyverse)
cor_melt <- cor_matrix %>%
as.data.frame() %>%
rownames_to_column("Var1") %>%
pivot_longer(-Var1, names_to = "Var2", values_to = "value")
ggplot(cor_melt, aes(x = Var1, y = Var2, fill = value)) +
geom_tile(color = "white") +
geom_text(aes(label = round(value, 2)), size = 3.2, color = "white", fontface = "bold") +
scale_fill_gradient2(low = "#c0392b", mid = "white", high = "#2980b9",
midpoint = 0, limits = c(-1, 1), name = "Korelasi") +
labs(
title = "Heatmap Matriks Korelasi",
subtitle = "Korelasi Pearson | nilai mendekati ±1 = hubungan kuat",
x = NULL, y = NULL,
caption = "Sumber: Coffee Chain Dataset"
) +
theme_minimal(base_size = 11) +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
plot.title = element_text(face = "bold"),
plot.subtitle = element_text(color = "grey40")
)Interpretasi korelasi:
##
## Call:
## lm(formula = Profit ~ Sales, data = df_clean)
##
## Residuals:
## Min 1Q Median 3Q Max
## -606.28 -9.15 11.77 28.31 466.85
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -42.456004 1.527850 -27.79 <2e-16 ***
## Sales 0.536582 0.006233 86.08 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 61.39 on 4246 degrees of freedom
## Multiple R-squared: 0.6357, Adjusted R-squared: 0.6357
## F-statistic: 7410 on 1 and 4246 DF, p-value: < 2.2e-16
Interpretasi Regresi Sederhana:
Berdasarkan output R, model menghasilkan:
##
## Call:
## lm(formula = Profit ~ Sales + Margin, data = df_clean)
##
## Residuals:
## Min 1Q Median 3Q Max
## -185.53 -14.70 2.55 19.43 161.73
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -28.68947 0.86939 -33.00 <2e-16 ***
## Sales -0.37973 0.01016 -37.39 <2e-16 ***
## Margin 1.56357 0.01627 96.09 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 34.46 on 4245 degrees of freedom
## Multiple R-squared: 0.8853, Adjusted R-squared: 0.8852
## F-statistic: 1.638e+04 on 2 and 4245 DF, p-value: < 2.2e-16
# Tabel perbandingan model
comp_df <- data.frame(
Model = c("Regresi Sederhana (Profit ~ Sales)",
"Regresi Berganda (Profit ~ Sales + Margin)"),
R_squared = c(round(summary(model_simple)$r.squared, 4),
round(summary(model_multi)$r.squared, 4)),
Adj_R2 = c(round(summary(model_simple)$adj.r.squared, 4),
round(summary(model_multi)$adj.r.squared, 4)),
RMSE = c(round(sqrt(mean(residuals(model_simple)^2)), 2),
round(sqrt(mean(residuals(model_multi)^2)), 2))
)
kable(comp_df, caption = "Perbandingan performa model regresi")| Model | R_squared | Adj_R2 | RMSE |
|---|---|---|---|
| Regresi Sederhana (Profit ~ Sales) | 0.6357 | 0.6357 | 61.38 |
| Regresi Berganda (Profit ~ Sales + Margin) | 0.8853 | 0.8852 | 34.44 |
Interpretasi Regresi Berganda:
Berdasarkan output R, penambahan variabel Margin
menghasilkan perubahan dramatis:
Kesimpulan regresi: Terbukti bahwa dalam konteks Coffee Chain, margin per unit produk jauh lebih menentukan profit dibandingkan volume penjualan. Strategi bisnis yang hanya mengejar peningkatan sales tanpa memperhatikan struktur margin berisiko memperburuk profitabilitas secara keseluruhan.
Interpretasi diagnostik: Plot residual membantu memverifikasi asumsi linearitas dan normalitas. Penyimpangan yang teridentifikasi pada titik ekstrem konsisten dengan adanya outlier pada segmen Tea-West yang telah diidentifikasi sebelumnya.
# Segmentasi produk berdasarkan kombinasi Sales dan Profit relatif terhadap median
med_sales <- median(df_clean$Sales)
med_profit <- median(df_clean$Profit)
df_seg <- df_clean %>%
mutate(
Segment = case_when(
Sales >= med_sales & Profit >= med_profit ~ "Star (Sales Tinggi, Profit Tinggi)",
Sales >= med_sales & Profit < med_profit ~ "Drainer (Sales Tinggi, Profit Rendah)",
Sales < med_sales & Profit >= med_profit ~ "Niche (Sales Rendah, Profit Tinggi)",
TRUE ~ "Weak (Sales Rendah, Profit Rendah)"
)
)
# Ringkasan per segmen
seg_summary <- df_seg %>%
group_by(Segment) %>%
summarise(
N = n(),
Avg_Sales = round(mean(Sales), 1),
Avg_Profit = round(mean(Profit), 1),
Avg_Rate = round(mean(Profit_Rate), 1),
Pct_Total = round(n() / nrow(df_seg) * 100, 1),
.groups = "drop"
) %>%
arrange(desc(Avg_Profit))
kable(seg_summary, caption = "Ringkasan statistik per segmen kinerja")| Segment | N | Avg_Sales | Avg_Profit | Avg_Rate | Pct_Total |
|---|---|---|---|---|---|
| Star (Sales Tinggi, Profit Tinggi) | 1715 | 316.7 | 138.3 | 42.4 | 40.4 |
| Niche (Sales Rendah, Profit Tinggi) | 448 | 110.5 | 49.0 | 47.3 | 10.5 |
| Drainer (Sales Tinggi, Profit Rendah) | 412 | 186.1 | 1.0 | -0.2 | 9.7 |
| Weak (Sales Rendah, Profit Rendah) | 1673 | 90.0 | 0.0 | -18.7 | 39.4 |
ggplot(df_seg, aes(x = Sales, y = Profit, color = Segment)) +
geom_point(alpha = 0.3, size = 1.5) +
geom_hline(yintercept = med_profit, linetype = "dashed", color = "grey50") +
geom_vline(xintercept = med_sales, linetype = "dashed", color = "grey50") +
geom_hline(yintercept = 0, color = "red", linewidth = 0.8) +
scale_color_manual(values = c(
"Star (Sales Tinggi, Profit Tinggi)" = "#27ae60",
"Drainer (Sales Tinggi, Profit Rendah)" = "#e74c3c",
"Niche (Sales Rendah, Profit Tinggi)" = "#3498db",
"Weak (Sales Rendah, Profit Rendah)" = "#95a5a6"
)) +
annotate("text", x = max(df_seg$Sales)*0.85, y = max(df_seg$Profit)*0.85,
label = "STAR", fontface = "bold", color = "#27ae60", size = 5) +
annotate("text", x = max(df_seg$Sales)*0.85, y = min(df_seg$Profit)*0.85,
label = "DRAINER", fontface = "bold", color = "#e74c3c", size = 5) +
labs(
title = "Peta Segmentasi Kinerja: Sales vs Profit",
subtitle = "Garis merah = titik impas | Garis abu = nilai median",
x = "Sales (USD)",
y = "Profit (USD)",
color = "Segmen",
caption = "Sumber: Coffee Chain Dataset"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold"),
plot.subtitle = element_text(color = "grey40"),
legend.position = "bottom",
legend.text = element_text(size = 8)
)Interpretasi segmentasi: Dari tabel, segmen Star (40.4% transaksi) adalah mesin profit utama dengan Profit Rate rata-rata 42.4%. Segmen Niche meski volume kecil memiliki Profit Rate tertinggi (47.3%) — produk-produk ini efisien dan layak dikembangkan. Yang paling kritis adalah segmen Drainer (9.7% transaksi): Sales-nya di atas median (186.1 USD) namun Profit Rate hampir nol (-0.2%) — biaya operasional yang dikeluarkan untuk mendukung volume tinggi ini tidak terbayar oleh profit yang memadai. Segmen Weak (39.4%) dengan Profit Rate -18.7% adalah segmen paling merugi secara rata-rata.
set.seed(42)
# Persiapan data clustering
cluster_data <- df_clean %>%
select(Sales, Profit, Margin, Marketing) %>%
scale() %>%
as.data.frame()
# Menentukan jumlah kluster optimal dengan Elbow Method
wss <- sapply(1:8, function(k) {
kmeans(cluster_data, centers = k, nstart = 25)$tot.withinss
})
elbow_df <- data.frame(k = 1:8, WSS = wss)
ggplot(elbow_df, aes(x = k, y = WSS)) +
geom_line(color = "steelblue", linewidth = 1) +
geom_point(color = "steelblue", size = 3) +
geom_vline(xintercept = 3, linetype = "dashed", color = "red") +
annotate("text", x = 3.2, y = max(wss)*0.85, label = "k = 3 optimal",
color = "red", hjust = 0) +
labs(
title = "Elbow Method untuk Menentukan Jumlah Kluster Optimal",
x = "Jumlah Kluster (k)",
y = "Within-Cluster Sum of Squares (WSS)"
) +
theme_minimal(base_size = 12) +
theme(plot.title = element_text(face = "bold"))# Fit k-means dengan k = 3
km_model <- kmeans(cluster_data, centers = 3, nstart = 50)
df_cluster <- df_clean %>%
mutate(Cluster = factor(km_model$cluster))
# Karakteristik tiap kluster
cluster_profile <- df_cluster %>%
group_by(Cluster) %>%
summarise(
N = n(),
Avg_Sales = round(mean(Sales), 1),
Avg_Profit = round(mean(Profit), 1),
Avg_Margin = round(mean(Margin), 1),
Avg_Mktg = round(mean(Marketing), 1),
Avg_Rate = round(mean(Profit_Rate), 1),
.groups = "drop"
) %>%
mutate(
Label = case_when(
Avg_Sales == max(Avg_Sales) ~ "Kluster Unggulan",
Avg_Profit == min(Avg_Profit) ~ "Kluster Bermasalah",
TRUE ~ "Kluster Menengah"
)
)
kable(cluster_profile,
caption = "Profil karakteristik tiap kluster K-Means (k=3)")| Cluster | N | Avg_Sales | Avg_Profit | Avg_Margin | Avg_Mktg | Avg_Rate | Label |
|---|---|---|---|---|---|---|---|
| 1 | 406 | 581.6 | 267.0 | 328.7 | 79.3 | 45.2 | Kluster Unggulan |
| 2 | 1165 | 253.3 | 96.6 | 142.6 | 41.3 | 37.3 | Kluster Menengah |
| 3 | 2677 | 107.8 | 14.4 | 53.6 | 19.5 | 0.3 | Kluster Bermasalah |
ggplot(df_cluster, aes(x = Sales, y = Profit, color = Cluster)) +
geom_point(alpha = 0.35, size = 1.5) +
geom_hline(yintercept = 0, color = "red", linewidth = 0.8, linetype = "dashed") +
scale_color_manual(values = c("1" = "#27ae60", "2" = "#e74c3c", "3" = "#f39c12"),
labels = cluster_profile$Label) +
labs(
title = "Visualisasi Hasil K-Means Clustering (k = 3)",
subtitle = "Garis merah = titik impas profitabilitas",
x = "Sales (USD)", y = "Profit (USD)",
color = "Kluster",
caption = "Sumber: Coffee Chain Dataset"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold"),
plot.subtitle = element_text(color = "grey40"),
legend.position = "right"
)Interpretasi clustering: K-Means berhasil memisahkan observasi ke dalam tiga kluster yang bermakna secara bisnis. Kluster Unggulan (n=406) memiliki rata-rata Sales 581.6 USD dan Profit 267.0 USD dengan Profit Rate 45.2% — ini adalah transaksi-transaksi bervolume besar sekaligus sangat efisien. Kluster Menengah (n=1.165) beroperasi dengan Profit Rate 37.3%, cukup sehat namun dengan skala lebih kecil. Kluster Bermasalah (n=2.677, mayoritas 63% data) memiliki rata-rata Profit Rate hanya 0.3% — hampir tidak menghasilkan profit sama sekali meski tetap beroperasi. Kluster ini yang paling mendesak untuk dievaluasi struktur biayanya.
Berdasarkan seluruh rangkaian analisis, terdapat lima temuan utama yang memiliki implikasi langsung terhadap pengambilan keputusan bisnis:
1. Margin adalah penentu profit yang lebih kuat daripada Sales. Hasil regresi berganda membuktikan ini secara kuantitatif: koefisien Margin = 1.564 vs koefisien Sales = -0.380 (negatif setelah Margin dikontrol). Artinya, mengejar volume Sales tanpa memperbaiki Margin justru kontraproduktif — setiap 1 USD tambahan Sales yang tidak diikuti peningkatan Margin berpotensi mengurangi profit.
2. Kategori Tea adalah profit destroyer terbesar. Dengan rata-rata Profit Rate -15.31%, Tea adalah satu-satunya kategori yang secara agregat merugi. Ketika dipersempit ke level wilayah, kombinasi Tea di West mencapai -98.3% — artinya setiap 100 USD yang terjual di segmen ini menghasilkan kerugian hampir 100 USD. Ini adalah prioritas intervensi tertinggi.
3. Wilayah West mengalami inefisiensi sistemik. West adalah satu-satunya wilayah dengan Profit Rate agregat negatif (-8.87%), meski memiliki total sales tertinggi kedua (272.264 USD). Paradoks ini — sales besar namun profit negatif — mengindikasikan bahwa ada faktor struktural seperti biaya distribusi lebih tinggi, margin produk yang lebih tertekan, atau bauran produk yang tidak optimal di wilayah ini.
4. Marketing spend tidak berkorelasi dengan profit (r = 0.225). Temuan ini mengindikasikan adanya misalokasi anggaran pemasaran. Kemungkinan besar pengeluaran marketing terbesar justru dialokasikan ke segmen yang secara struktural tidak menguntungkan (Tea-West), sehingga efeknya tidak terkonversi menjadi profit.
5. Espresso adalah kategori paling konsisten menguntungkan. Dengan distribusi Profit Rate yang stabil di atas nol dan variabilitas rendah, kategori Espresso — terutama Caffe Mocha dan Regular Espresso — adalah cash cow yang perlu dijaga dan diperluas kapasitasnya, bukan dikanibal oleh diversifikasi produk yang tidak menguntungkan.
| Prioritas | Area | Rekomendasi |
|---|---|---|
| 🔴 Tinggi | Produk Tea | Lakukan audit biaya menyeluruh pada kategori Tea. Pertimbangkan repricing atau discontinuation pada varian yang defisit kronis (Earl Grey, Lemon). |
| 🔴 Tinggi | Wilayah West | Investigasi struktur biaya wilayah West. Evaluasi apakah ada peluang renegoisasi kontrak distribusi atau penyesuaian portofolio produk. |
| 🟡 Menengah | Alokasi Marketing | Realokasikan anggaran marketing dari segmen Tea-West ke Espresso-Central/South yang terbukti menghasilkan ROI lebih tinggi. |
| 🟡 Menengah | Harga Tea | Naikkan harga jual produk Tea minimal 15–20% untuk menutup gap margin, atau lakukan efisiensi COGS melalui renegosiasi pemasok. |
| 🟢 Oportunitas | Ekspansi Espresso | Tingkatkan ketersediaan dan promosi Espresso di wilayah South dan Central yang menunjukkan Profit Rate tertinggi. |
Laporan ini telah melakukan analisis profitabilitas komprehensif terhadap 4.248 catatan transaksi Coffee Chain menggunakan pendekatan multimetode — korelasi, regresi, segmentasi, dan clustering.
Kesimpulan utama yang dapat ditarik adalah:
Hubungan Sales-Profit tidak linear dan tidak universal. Terdapat segmen-segmen spesifik di mana peningkatan sales justru disertai pemborosan biaya yang lebih besar, menghasilkan profit negatif.
Margin adalah variabel kunci yang harus menjadi fokus utama manajemen, bukan hanya laporan penjualan. Peningkatan 1 USD dalam Margin memiliki dampak lebih besar terhadap profit dibandingkan peningkatan 1 USD dalam Sales.
Inefisiensi bersifat terkonsentrasi, bukan merata — kategori Tea dan wilayah West adalah dua kutub masalah yang perlu penanganan segera dan berbeda dari strategi bisnis keseluruhan.
K-Means clustering berhasil mengidentifikasi tiga kluster bisnis yang bermakna operasional: kluster unggulan, menengah, dan bermasalah — memberikan dasar objektif bagi alokasi sumber daya dan prioritas intervensi manajerial.
Dengan memahami dinamika ini secara kuantitatif, manajemen Coffee Chain dapat bergeser dari pengambilan keputusan berbasis intuisi menuju keputusan berbasis bukti (evidence-based decision making) yang lebih akuntabel dan berdampak nyata pada bottom line perusahaan.