Industri kopi merupakan salah satu sektor pada bidang makanan dan minuman yang terus berkembang dan banyak diminati oleh masyarakat. Banyaknya peminat dalam mengonsumsi kopi membuat semakin banyak coffe shop yang menjadikan lingkungan persaingan semakin ketat. Oleh sebab itu tujuan dari analisis ini adalah untuk membantu para investor atau pemilih usaha coffe shop agar mampu memahami kondisi pasar dan mampu mengatur strategi yang baik dan tepat sasaran.
Setelah diteliti dan dicari tahu, dataset yang saya gunakan dalam analisis ini berasal dari Tableau Community Repository milik Tableau yang sudah umum digunakan untuk latihan. Dataset Coffee Chain berisi data transaksi penjualan produk kopi dan berbagai jenis minuman dari sebuah jaringan kedai kopi di Amerika Serikat. Data terdiri dari 4.248 observasi dan 20 variabel, yang meliputi informasi pasar, jenis produk, anggaran, serta realisasi penjualan dan profit.
Langkah awal yang perlu kita lakukan adalah load library, untuk semua library yg akan digunakan. Lebih baik lakukan load di awal agar nanti di tengah sudah tidak perlu load library lagi dan meminimalisir eror. Kemudian dilanjutkan juga dengan melakukan impor dataset yang akan digunakan, saya menggunkan dataset yang telah diunduh. Untuk packages import dataset juga disesuaikan dengan jenis dataset yg akan digunakan, karena data yg saya gunakan memiliki format xlsx maka saya menggunakan read_excel.
library(tidyverse) # Manipulasi data dan visualisasi
library(readxl) # Membaca file Excel
library(lubridate) # Mengolah data tanggal
library(corrplot) # Heatmap korelasi
library(car) # Uji VIF multikolinearitas
library(lmtest) # Uji Breusch-Pagan dan Durbin-Watson
library(tseries) # Uji ADF stasioneritas
library(forecast) # Dekomposisi time series
library(scales) # Format label grafik
library(knitr) # Tabel di HTML
library(kableExtra) # Styling tabelEksplorasi berikut digunakan untuk mengetahui ukuran data, struktur data, tipe data dan nama data.
## 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…
## $ Market <chr> "Central", "Central", "Central", "Central", "Central"…
## $ `Market Size` <chr> "Major Market", "Major Market", "Major Market", "Majo…
## $ Product <chr> "Amaretto", "Colombian", "Decaf Irish Cream", "Green …
## $ `Product Line` <chr> "Beans", "Beans", "Beans", "Leaves", "Beans", "Beans"…
## $ `Product Type` <chr> "Coffee", "Coffee", "Coffee", "Tea", "Espresso", "Esp…
## $ State <chr> "Colorado", "Colorado", "Colorado", "Colorado", "Colo…
## $ Type <chr> "Regular", "Regular", "Decaf", "Regular", "Regular", …
## $ `Budget COGS` <dbl> 90, 80, 100, 30, 60, 80, 140, 50, 50, 40, 50, 150, 10…
## $ `Budget Margin` <dbl> 130, 110, 140, 50, 90, 130, 160, 80, 70, 70, 70, 210,…
## $ `Budget Profit` <dbl> 100, 80, 110, 30, 70, 80, 110, 20, 40, 20, 40, 130, 1…
## $ `Budget Sales` <dbl> 220, 190, 240, 80, 150, 210, 300, 130, 120, 110, 120,…
## $ COGS <dbl> 89, 83, 95, 44, 54, 72, 170, 63, 60, 58, 64, 144, 95,…
## $ Inventory <dbl> 777, 623, 821, 623, 456, 558, 1091, 435, 336, 338, 96…
## $ Margin <dbl> 130, 107, 139, 56, 80, 108, 171, 87, 80, 72, 76, 201,…
## $ Marketing <dbl> 24, 27, 26, 14, 15, 23, 47, 57, 19, 22, 19, 47, 30, 7…
## $ Profit <dbl> 94, 68, 101, 30, 54, 53, 99, 0, 33, 17, 36, 111, 87, …
## $ 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, 1…
Kemudian dilanjutkan dengan mengetahui nilai minimum, maximum, mean, median dan quartil untuk beberapa variabel. Rumus-rumus tersebut secara garis besarnya adalah sebagai berikut: Mean(rata-rata) : \[\bar{x} = \frac{1}{n} \sum_{i=1}^{n} x_i\] Median: \[\tilde{x} = \begin{cases} x_{\left(\frac{n+1}{2}\right)} & \text{jika } n \text{ ganjil} \\ \frac{x_{\left(\frac{n}{2}\right)} + x_{\left(\frac{n}{2}+1\right)}}{2} & \text{jika } n \text{ genap} \end{cases}\] Minimum: \[x_{\min} = \min_{1 \leq i \leq n}(x_i)\] Maximum: \[x_{\max} = \max_{1 \leq i \leq n}(x_i)\] Quartil: \[Q_k = x_{\left(\frac{k(n+1)}{4}\right)}, \quad k = 1, 2, 3\]
dan diperoleh hasil sebagai berikut:
df %>%
select(Sales, Marketing, COGS, `Total Expenses`, Margin, Profit) %>%
summary() %>%
kable(caption = "Statistik Deskriptif Variabel Numerik") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE)| Sales | Marketing | COGS | Total Expenses | Margin | Profit | |
|---|---|---|---|---|---|---|
| Min. : 17 | Min. : 0.00 | Min. : 0.00 | Min. : 10.00 | Min. :-302.00 | Min. :-638.0 | |
| 1st Qu.:100 | 1st Qu.: 13.00 | 1st Qu.: 43.00 | 1st Qu.: 33.00 | 1st Qu.: 52.75 | 1st Qu.: 17.0 | |
| Median :138 | Median : 22.00 | Median : 60.00 | Median : 46.00 | Median : 76.00 | Median : 40.0 | |
| Mean :193 | Mean : 31.19 | Mean : 84.43 | Mean : 54.06 | Mean : 104.29 | Mean : 61.1 | |
| 3rd Qu.:230 | 3rd Qu.: 39.00 | 3rd Qu.:100.00 | 3rd Qu.: 65.00 | 3rd Qu.: 132.00 | 3rd Qu.: 92.0 | |
| Max. :912 | Max. :156.00 | Max. :364.00 | Max. :190.00 | Max. : 613.00 | Max. : 778.0 |
colSums(is.na(df)) %>%
kable(col.names = "Jumlah NA", caption = "Cek Missing Values per Kolom") %>%
kable_styling(full_width = FALSE,
bootstrap_options = c("striped", "hover"))| Jumlah NA | |
|---|---|
| Area Code | 0 |
| Date | 0 |
| Market | 0 |
| Market Size | 0 |
| Product | 0 |
| Product Line | 0 |
| Product Type | 0 |
| State | 0 |
| Type | 0 |
| Budget COGS | 0 |
| Budget Margin | 0 |
| Budget Profit | 0 |
| Budget Sales | 0 |
| COGS | 0 |
| Inventory | 0 |
| Margin | 0 |
| Marketing | 0 |
| Profit | 0 |
| Sales | 0 |
| Total Expenses | 0 |
Cek missing value dilakukan untuk mengetahui apakah terdapat nilai yang kosong, karena nantinya ini akan memengaruhi pada proses analisis juga. Dan dari hasil cek tersebut, tidak terdapat missing values pada seluruh variabel dataset.
Konversi dilakukan karena masih terdapat beberapa variabel yang memiliki tipe data yang salah dan tidak sesuai tujuan kita.
df <- df %>%
mutate(
Date = as.Date(Date),
`Product Type` = as.factor(`Product Type`),
`Market Size` = as.factor(`Market Size`),
Market = as.factor(Market),
Type = as.factor(Type),
ProductType = `Product Type`,
MarketSize = `Market Size`
)ggplot(df, aes(x = Profit)) +
geom_histogram(bins = 50, fill = "#2c7bb6", color = "white", alpha = 0.85) +
geom_vline(xintercept = mean(df$Profit),
color = "red", linetype = "dashed", linewidth = 1) +
labs(
title = "Distribusi Profit Coffee Chain",
subtitle = "Garis merah = nilai rata-rata Profit",
x = "Profit", y = "Frekuensi"
) +
theme_minimal(base_size = 13) +
theme(plot.title = element_text(face = "bold"))Distribusi Profit bersifat right-skewed yang berarti mayoritas transaksi menghasilkan profit rendah hingga sedang (ditunjukkan dengan lebih banyak nilai dibawah garis rata-rata), sementara sebagian kecil menghasilkan profit sangat tinggi yang membentuk ekor panjang di kanan.
num_vars <- df %>%
select(Sales, Marketing, COGS, `Total Expenses`, Inventory, Margin, Profit)
corrplot(
cor(num_vars),
method = "color",
type = "upper",
addCoef.col = "black",
tl.col = "black",
tl.srt = 45,
number.cex = 0.75,
title = "Matriks Korelasi Variabel Numerik",
mar = c(0, 0, 1.5, 0)
)Margin (r = 0.92) dan Sales (r = 0.80) memiliki korelasi paling kuat terhadap Profit.
ggplot(df, aes(x = `Product Type`, y = Profit, fill = `Market Size`)) +
geom_boxplot(alpha = 0.8, outlier.alpha = 0.3) +
scale_fill_manual(values = c("#E07A5F", "#3D405B")) +
labs(
title = "Distribusi Profit berdasarkan Product Type dan Market Size",
x = "Product Type", y = "Profit", fill = "Market Size"
) +
theme_minimal(base_size = 13) +
theme(plot.title = element_text(face = "bold"))Transaksi di Major Market menghasilkan profit lebih tinggi dibanding Small Market pada semua jenis produk.
Perusahaan beroperasi di empat wilayah pasar: Central, East, South, dan West. Aanalisis ini dilakukan untuk mengetahui market mana yang menghasilkan total Sales dan Profit tertinggi, serta apakah terdapat perbedaan profit antar market?
market_summary <- df %>%
group_by(Market) %>%
summarise(
Total_Sales = sum(Sales),
Total_Profit = sum(Profit),
Avg_Margin = mean(Margin),
.groups = "drop"
) %>%
arrange(desc(Total_Profit))ggplot(market_summary,
aes(x = reorder(Market, -Total_Profit),
y = Total_Profit, fill = Market)) +
geom_col(width = 0.6, show.legend = FALSE) +
geom_text(aes(label = comma(Total_Profit)),
vjust = -0.5, size = 4, fontface = "bold") +
scale_y_continuous(labels = comma,
expand = expansion(mult = c(0, 0.12))) +
scale_fill_manual(values = c(
"Central" = "#9B8EC7",
"East" = "#F891BB",
"South" = "#F9D0CD",
"West" = "#B4D3D9"
)) +
labs(
title = "Total Profit per Market Region",
subtitle = "Periode Januari 2012 – Desember 2013",
x = "Market Region", y = "Total Profit"
) +
theme_minimal(base_size = 13) +
theme(plot.title = element_text(face = "bold"))ggplot(df, aes(x = Market, y = Profit, fill = Market)) +
geom_boxplot(show.legend = FALSE, outlier.alpha = 0.3) +
scale_fill_manual(values = c(
"Central" = "#9B8EC7",
"East" = "#F891BB",
"South" = "#F9D0CD",
"West" = "#B4D3D9"
)) +
scale_y_continuous(labels = comma) +
labs(
title = "Distribusi Profit per Market Region",
subtitle = "Setiap titik mewakili satu transaksi",
x = "Market Region", y = "Profit"
) +
theme_minimal(base_size = 13) +
theme(plot.title = element_text(face = "bold"))market_summary %>%
mutate(
Total_Sales = comma(Total_Sales),
Total_Profit = comma(Total_Profit),
Avg_Margin = round(Avg_Margin, 2)
) %>%
rename(
"Market" = Market,
"Total Sales" = Total_Sales,
"Total Profit" = Total_Profit,
"Rata-rata Margin" = Avg_Margin
) %>%
kable(caption = "Ringkasan Performa per Market Region") %>%
kable_styling(bootstrap_options = c("striped", "hover"),
full_width = FALSE)| Market | Total Sales | Total Profit | Rata-rata Margin |
|---|---|---|---|
| Central | 265,045 | 93,852 | 108.82 |
| West | 272,264 | 73,996 | 104.21 |
| East | 178,576 | 59,217 | 111.42 |
| South | 103,926 | 32,478 | 86.00 |
- Market Central mencatat total Profit tertinggi, diikuti West, East, dan South.
- Boxplot menunjukkan adanya outlier di semua region, terutama transaksi dengan profit negatif. ## One-Way ANOVA: Profit antar Market
## Df Sum Sq Mean Sq F value Pr(>F)
## Market 3 288811 96270 9.361 3.64e-06 ***
## Residuals 4244 43644825 10284
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
tukey_market <- TukeyHSD(anova_market)
tukey_market_df <- as.data.frame(tukey_market$Market) %>%
rownames_to_column("Pasangan") %>%
rename(
Selisih = diff,
`CI Bawah` = lwr,
`CI Atas` = upr,
`p-value adj` = `p adj`
) %>%
mutate(Signifikan = ifelse(`p-value adj` < 0.05, "Ya ✓", "Tidak"))
tukey_market_df %>%
kable(digits = 3, caption = "Post-Hoc Tukey HSD: Profit antar Market") %>%
kable_styling(bootstrap_options = c("striped", "hover"),
full_width = FALSE) %>%
row_spec(which(tukey_market_df$Signifikan == "Ya ✓"),
background = "#E8F5E9")| Pasangan | Selisih | CI Bawah | CI Atas | p-value adj | Signifikan |
|---|---|---|---|---|---|
| East-Central | -3.145 | -14.416 | 8.126 | 0.890 | Tidak |
| South-Central | -21.500 | -33.813 | -9.187 | 0.000 | Ya ✓ |
| West-Central | -14.774 | -24.828 | -4.720 | 0.001 | Ya ✓ |
| South-East | -18.355 | -31.681 | -5.030 | 0.002 | Ya ✓ |
| West-East | -11.629 | -22.900 | -0.358 | 0.040 | Ya ✓ |
| West-South | 6.726 | -5.587 | 19.040 | 0.497 | Tidak |
Hasil One-Way ANOVA: Karena nilai p-value < 0,05, Maka H₀ ditolak yang berarti terdapat perbedaan rata-rata profit yang signifikan antar market. Uji Tukey mengidentifikasi pasangan market mana yang berbeda secara spesifik — baris hijau pada tabel = pasangan yang berbeda signifikan.
## Df Sum Sq Mean Sq F value Pr(>F)
## ProductType 3 141680 47227 5.006 0.00182 **
## MarketSize 1 2641586 2641586 279.988 < 2e-16 ***
## ProductType:MarketSize 3 1147469 382490 40.541 < 2e-16 ***
## Residuals 4240 40002902 9435
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
df %>%
group_by(ProductType, MarketSize) %>%
summarise(Mean_Profit = mean(Profit), .groups = "drop") %>%
ggplot(aes(x = ProductType, y = Mean_Profit,
color = MarketSize, group = MarketSize)) +
geom_line(linewidth = 1.3) +
geom_point(size = 3.5) +
scale_color_manual(values = c("#E07A5F", "#3D405B")) +
labs(
title = "Interaction Plot: Rata-rata Profit",
subtitle = "Product Type × Market Size",
x = "Product Type", y = "Rata-rata Profit",
color = "Market Size"
) +
theme_minimal(base_size = 13) +
theme(plot.title = element_text(face = "bold"))Hasil Two-Way ANOVA mengonfirmasi bahwa Major Market secara konsisten menghasilkan profit jauh lebih tinggi dari Small Market pada semua jenis produk. Interaction effect yang signifikan menunjukkan bahwa dampak Market Size berbeda-beda tergantung jenis produknya.
Analisis tren bertujuan melihat pola perubahan Sales dan Profit secara bulanan selama periode 2012–2013, termasuk mendeteksi adanya pola musiman (seasonality).
Karena kita mau melihat tren waktu ke waktu dan karena datanya berisi transaksi tiap hari maka dikelompokkan per bulan agar lebih mudahkan dalam visualisasi dan analisis.
df_tren_total <- df %>%
mutate(Periode = floor_date(Date, "month")) %>%
group_by(Periode) %>%
summarise(
Total_Sales = sum(Sales),
Total_Profit = sum(Profit),
Total_Marketing = sum(Marketing),
.groups = "drop"
)
df_tren <- df %>%
mutate(Periode = floor_date(Date, "month")) %>%
group_by(Periode, ProductType) %>%
summarise(
Total_Sales = sum(Sales),
Total_Profit = sum(Profit),
.groups = "drop"
)
df_tren_total %>%
rename(Bulan = Periode, Sales = Total_Sales,
Profit = Total_Profit, Marketing = Total_Marketing) %>%
kable(caption = "Ringkasan Bulanan: Sales, Profit, dan Marketing") %>%
kable_styling(bootstrap_options = c("striped", "hover"),
full_width = FALSE)| Bulan | Sales | Profit | Marketing |
|---|---|---|---|
| 2012-01-01 | 31555 | 8041 | 5223 |
| 2012-02-01 | 32092 | 8369 | 5289 |
| 2012-03-01 | 32245 | 8365 | 5327 |
| 2012-04-01 | 32943 | 8670 | 5421 |
| 2012-05-01 | 33692 | 8947 | 5530 |
| 2012-06-01 | 35125 | 9571 | 5765 |
| 2012-07-01 | 36161 | 9905 | 5985 |
| 2012-08-01 | 36029 | 9566 | 6046 |
| 2012-09-01 | 33092 | 8508 | 5491 |
| 2012-10-01 | 32849 | 8674 | 5388 |
| 2012-11-01 | 32003 | 8399 | 5263 |
| 2012-12-01 | 33373 | 8811 | 5509 |
| 2013-01-01 | 35316 | 12524 | 5223 |
| 2013-02-01 | 34192 | 12419 | 5289 |
| 2013-03-01 | 34355 | 12415 | 5327 |
| 2013-04-01 | 35112 | 12863 | 5421 |
| 2013-05-01 | 33394 | 12348 | 5530 |
| 2013-06-01 | 34807 | 13218 | 5765 |
| 2013-07-01 | 35830 | 13671 | 5985 |
| 2013-08-01 | 35707 | 13205 | 6046 |
| 2013-09-01 | 35269 | 12627 | 5491 |
| 2013-10-01 | 34987 | 12878 | 5388 |
| 2013-11-01 | 34103 | 12460 | 5263 |
| 2013-12-01 | 35580 | 13089 | 5509 |
ggplot(df_tren_total, aes(x = Periode, y = Total_Sales)) +
geom_line(color = "#2c7bb6", linewidth = 1.2) +
geom_point(color = "#2c7bb6", size = 2.5) +
scale_x_date(date_breaks = "3 months", date_labels = "%b %Y") +
scale_y_continuous(labels = comma) +
labs(
title = "Tren Total Penjualan (Sales) Bulanan",
subtitle = "Periode Januari 2012 – Desember 2013",
x = "Periode", y = "Total Sales"
) +
theme_minimal(base_size = 13) +
theme(plot.title = element_text(face = "bold"),
axis.text.x = element_text(angle = 45, hjust = 1))ggplot(df_tren, aes(x = Periode, y = Total_Sales, color = ProductType)) +
geom_line(linewidth = 1.1) +
geom_point(size = 2) +
scale_x_date(date_breaks = "3 months", date_labels = "%b %Y") +
scale_y_continuous(labels = comma) +
scale_color_brewer(palette = "Set3") +
labs(
title = "Tren Penjualan per Jenis Produk",
subtitle = "Coffee, Tea, Espresso, dan Herbal Tea",
x = "Periode", y = "Total Sales", color = "Jenis Produk"
) +
theme_minimal(base_size = 13) +
theme(plot.title = element_text(face = "bold"),
axis.text.x = element_text(angle = 45, hjust = 1))ggplot(df_tren_total, aes(x = Periode, y = Total_Profit)) +
geom_area(fill = "#FBEFEF", alpha = 0.4) +
geom_line(color = "#F5AFAF", linewidth = 1.2) +
geom_point(color = "#F5AFAF", size = 2.5) +
scale_x_date(date_breaks = "3 months", date_labels = "%b %Y") +
scale_y_continuous(labels = comma) +
labs(
title = "Tren Total Profit Bulanan",
subtitle = "Periode Januari 2012 – Desember 2013",
x = "Periode", y = "Total Profit"
) +
theme_minimal(base_size = 13) +
theme(plot.title = element_text(face = "bold"),
axis.text.x = element_text(angle = 45, hjust = 1))ggplot(df_tren_total, aes(x = Periode)) +
geom_col(aes(y = Total_Marketing), fill = "#81B29A", alpha = 0.8) +
geom_line(aes(y = Total_Profit), color = "#E07A5F", linewidth = 1.2) +
geom_point(aes(y = Total_Profit), color = "#E07A5F", size = 2.5) +
scale_x_date(date_labels = "%b %Y", date_breaks = "2 months") +
scale_y_continuous(labels = comma) +
labs(
title = "Pengeluaran Marketing (batang) vs Profit (garis) Bulanan",
x = "Bulan", y = "Nilai"
) +
theme_minimal(base_size = 13) +
theme(plot.title = element_text(face = "bold"),
axis.text.x = element_text(angle = 45, hjust = 1))Dekomposisi adalah teknik memecah data menjadi beberapa komponen penyusun, supaya kita bisa melihat masing-masing pola secara terpisah dan lebih jelas. Data tersebut dipecah menjadi Data asli (observed),trend, seasonal dan sisa
ts_profit <- ts(df_tren_total$Total_Profit,
start = c(2012, 1), frequency = 12)
decomp <- decompose(ts_profit, type = "additive")
plot(decomp, title = "Dekomposisi Time Series: Total Profit Bulanan")Trend > - Total Sales menunjukkan adanya pola musiman dalam melakukan transaksi yang mungkin hal ini dipengaruhi oleh musim/cuaca yang ada di Amerika. > - Coffee secara konsisten menjadi produk dengan penjualan tertinggi sepanjang periode jika dibandingkan dengan minuman yang lain. > - Profit/Keuntungan juga terlihat terus meningkat, meskipun terkadang menurun dibeberapa waktu (yg disebabkan oleh faktor lain seperti cuaca) akan tetapi secara garis besar profit terus meningkat. > - Pengeluaran Marketing dan Profit bergerak saling memberikan timbal balik,yang artinya investasi marketing berkontribusi positif terhadap profit.
Pada tahap ini dilakukan analisis yang ditujukan untuk mengetahui variabel apa yang paling berpengaruh terhadap Profit.
Bentuk umum persamaan regresi linear berganda: \[Y = \beta_0 + \beta_1 X_1 + \beta_2 X_2 + \beta_3 X_3 + \cdots + \beta_p X_p + \varepsilon\] dan pada kasus ini kita akan membuktikan rumus: \[Profit = \beta_0 + \beta_1 \cdot Sales + \beta_2 \cdot Marketing + \beta_3 \cdot COGS + \beta_4 \cdot Total\ Expenses + \varepsilon\]
ggplot(df, aes(x = Sales, y = Profit)) +
geom_point(alpha = 0.25, color = "#4575b4") +
geom_smooth(method = "lm", color = "red", se = TRUE) +
scale_x_continuous(labels = comma) +
scale_y_continuous(labels = comma) +
labs(
title = "Hubungan antara Sales dan Profit",
subtitle = "Garis merah = garis regresi linear",
x = "Sales", y = "Profit"
) +
theme_minimal(base_size = 13) +
theme(plot.title = element_text(face = "bold"))model_regresi <- lm(
Profit ~ Sales + Marketing + COGS + `Total Expenses`,
data = df
)
summary(model_regresi)##
## Call:
## lm(formula = Profit ~ Sales + Marketing + COGS + `Total Expenses`,
## data = df)
##
## Residuals:
## Min 1Q Median 3Q Max
## -112.028 -5.748 0.526 5.525 105.228
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2.366873 0.705850 3.353 0.000806 ***
## Sales 1.208316 0.003721 324.744 < 2e-16 ***
## Marketing 0.195850 0.040466 4.840 1.35e-06 ***
## COGS -1.241869 0.010250 -121.156 < 2e-16 ***
## `Total Expenses` -1.400421 0.031161 -44.942 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 16.86 on 4243 degrees of freedom
## Multiple R-squared: 0.9726, Adjusted R-squared: 0.9725
## F-statistic: 3.76e+04 on 4 and 4243 DF, p-value: < 2.2e-16
coef_df <- as.data.frame(summary(model_regresi)$coefficients)
coef_df <- round(coef_df, 4)
colnames(coef_df) <- c("Koefisien", "Std. Error", "t-value", "p-value")
coef_df %>%
kable(caption = "Koefisien Model Regresi Linear Berganda") %>%
kable_styling(bootstrap_options = c("striped", "hover"),
full_width = FALSE) %>%
row_spec(which(coef_df$`p-value` < 0.05),
bold = TRUE, color = "white", background = "#CBDCEB")| Koefisien | Std. Error | t-value | p-value | |
|---|---|---|---|---|
| (Intercept) | 2.3669 | 0.7059 | 3.3532 | 8e-04 |
| Sales | 1.2083 | 0.0037 | 324.7442 | 0e+00 |
| Marketing | 0.1958 | 0.0405 | 4.8398 | 0e+00 |
| COGS | -1.2419 | 0.0103 | -121.1563 | 0e+00 |
Total Expenses
|
-1.4004 | 0.0312 | -44.9416 | 0e+00 |
Interpretasi Koefisien: - Sales berkoefisien positif signifikan yang berarti setiap kenaikan 1 unit Sales meningkatkan Profit secara bermakna. - COGS berkoefisien negatif signifikan berarti semakin tinggi biaya produksi maka semakin rendah Profit. - Marketing berkoefisien positif signifikan investasi marketing terbukti berkontribusi pada peningkatan Profit. - Total Expenses berkoefisien negatif signifikan yang berarti biaya operasional yang tinggi akan menurunkan Profit. - Nilai R² Adjusted yang sangat tinggi menunjukkan model mampu menjelaskan proporsi besar variasi Profit.
df_pred <- df %>%
mutate(
Predicted = predict(model_regresi),
Residual = Profit - Predicted
)
ggplot(df_pred, aes(x = Predicted, y = Profit)) +
geom_point(alpha = 0.25, color = "#2c7bb6") +
geom_abline(slope = 1, intercept = 0,
color = "red", linetype = "dashed", linewidth = 1) +
labs(
title = "Actual vs Predicted Profit",
subtitle = "Garis merah = prediksi sempurna",
x = "Predicted Profit", y = "Actual Profit"
) +
theme_minimal(base_size = 13) +
theme(plot.title = element_text(face = "bold"))Sebagian besar titik data mengikuti garis merah yang menunjukkan prediksi model cukup akurat.
ks_test <- ks.test(df_pred$Residual, "pnorm",
mean = mean(df_pred$Residual),
sd = sd(df_pred$Residual))
data.frame(
Uji = "Kolmogorov-Smirnov",
Statistik = round(ks_test$statistic, 4),
`p-value` = formatC(ks_test$p.value, format = "e", digits = 3),
Kesimpulan = ifelse(ks_test$p.value > 0.05,
"Normal",
"Tidak Normal"),
check.names = FALSE
) %>%
kable(caption = "Uji Normalitas Residual") %>%
kable_styling(full_width = FALSE,
bootstrap_options = c("striped", "hover"))| Uji | Statistik | p-value | Kesimpulan | |
|---|---|---|---|---|
| D | Kolmogorov-Smirnov | 0.1551 | 3.616e-89 | Tidak Normal |
Dari hasil uji normalitas diperoleh bahwa residunya tidak normal, akan tetapi jika kita melihat jumlah observasi yang sangat besar yaitu n = 4.248 kita dapat menggunakan CLT. Central Limit Theorem (CLT) mengatakan bahwa ketika sampel besar diambil secara acak, maka distribusi rata-rata sampel akan mendekati normal sehingga hasil inferensi tetap valid. Sehingga hal ini dapat diabaikan.
bp_test <- bptest(model_regresi)
data.frame(
Uji = "Breusch-Pagan",
Statistik = round(bp_test$statistic, 4),
`p-value` = formatC(bp_test$p.value, format = "e", digits = 3),
Kesimpulan = ifelse(bp_test$p.value > 0.05,
"Homoskedastis ✓",
"Heteroskedastis ✗"),
check.names = FALSE
) %>%
kable(caption = "Uji Homoskedastisitas (Breusch-Pagan)") %>%
kable_styling(full_width = FALSE,
bootstrap_options = c("striped", "hover"))| Uji | Statistik | p-value | Kesimpulan | |
|---|---|---|---|---|
| BP | Breusch-Pagan | 994.7779 | 4.834e-214 | Heteroskedastis ✗ |
Dari hasil uji homoskedastisitas menunjukkan bahawa terdapat Heteroskedastisitas yang hanya akan memengaruhi standard error.
vif_vals <- vif(model_regresi)
data.frame(
Variabel = names(vif_vals),
VIF = round(vif_vals, 3),
Kesimpulan = ifelse(vif_vals > 10,
"Multikolinearitas ✗",
"Aman ✓")
) %>%
kable(caption = "Variance Inflation Factor (VIF)") %>%
kable_styling(full_width = FALSE,
bootstrap_options = c("striped", "hover")) %>%
row_spec(which(vif_vals > 10),
bold = TRUE, color = "white", background = "#C0E1D2")| Variabel | VIF | Kesimpulan | |
|---|---|---|---|
| Sales | Sales | 4.727 | Aman ✓ |
| Marketing | Marketing | 17.874 | Multikolinearitas ✗ |
| COGS | COGS | 7.102 | Aman ✓ |
Total Expenses
|
Total Expenses
|
15.191 | Multikolinearitas ✗ |
Dari hasil uji Multikolinearitas, kita perlu berhati hati dengan variabel marketing dan total expenses, karena keduanya memiliki nilai VIF yang > 10.
dw_test <- dwtest(model_regresi)
data.frame(
Uji = "Durbin-Watson",
Statistik = round(dw_test$statistic, 4),
`p-value` = round(dw_test$p.value, 4),
Kesimpulan = ifelse(
dw_test$statistic >= 1.5 & dw_test$statistic <= 2.5,
"Tidak ada autokorelasi ✓",
"Terdapat autokorelasi ✗"
),
check.names = FALSE
) %>%
kable(caption = "Uji Autokorelasi (Durbin-Watson)") %>%
kable_styling(full_width = FALSE,
bootstrap_options = c("striped", "hover"))| Uji | Statistik | p-value | Kesimpulan | |
|---|---|---|---|---|
| DW | Durbin-Watson | 1.7888 | 0 | Tidak ada autokorelasi ✓ |
Hasil uji autokorelasi memberikan hasil 1,79 yang menandakan tidak ada autokorelasi antar residual, artinya residual bersifat independen satu sama lain.
data.frame(
No = 1:4,
Asumsi = c("Normalitas Residual", "Homoskedastisitas",
"Multikolinearitas", "Autokorelasi"),
Metode = c("Kolmogorov-Smirnov", "Breusch-Pagan",
"VIF", "Durbin-Watson"),
Status = c(
"⚠ Tidak normal — CLT berlaku (n besar)",
ifelse(bp_test$p.value > 0.05,
"✓ Terpenuhi", "⚠ Heteroskedastis — limitasi model"),
ifelse(all(vif_vals < 10),
"✓ Terpenuhi", "⚠ Ada multikolinearitas — limitasi model"),
ifelse(dw_test$statistic >= 1.5 & dw_test$statistic <= 2.5,
"✓ Terpenuhi", "⚠ Ada autokorelasi")
)
) %>%
kable(caption = "Ringkasan Hasil Uji Asumsi Regresi") %>%
kable_styling(full_width = FALSE,
bootstrap_options = c("striped", "hover")) %>%
column_spec(4, bold = TRUE)| No | Asumsi | Metode | Status |
|---|---|---|---|
| 1 | Normalitas Residual | Kolmogorov-Smirnov | ⚠ Tidak normal — CLT berlaku (n besar) |
| 2 | Homoskedastisitas | Breusch-Pagan | ⚠ Heteroskedastis — limitasi model |
| 3 | Multikolinearitas | VIF | ⚠ Ada multikolinearitas — limitasi model |
| 4 | Autokorelasi | Durbin-Watson | ✓ Terpenuhi |
| No | Rumusan | Hasil |
|---|---|---|
| 1 | Performa antar Market | Market Central mencatat profit tertinggi. Perbedaan antar market cukup signifikan secara statistik. Major Market secara konsisten lebih menghasilkan profit dari Small Market. |
| 2 | Tren Penjualan | Tren Sales dan Profit meningkat dari 2012 ke 2013 dan cenderung memiliki pola musiman. Coffee mendominasi penjualan sepanjang periode. |
| 3 | Faktor yang mempengaruhi Profit | Sales berpengaruh positif terkuat terhadap Profit. COGS dan Total Expenses berpengaruh negatif signifikan. R² sangat tinggi menunjukkan model fit baik. |
Sistem Informasi Manajemen - G Universitas Sebelas Maret