Analisis Rantai Markov

DISUSUN OLEH KELOMPOK 3 MATAKULIAH PROSES STOKASTIK

  1. Angelia Yuflih Pambayun (23031030002)
  2. Safira Wafda Danantika (23031030009)
  3. Devi Roslidiyanti (23031030024)
  4. Gilang Adi Prasetyo (23031030040)
  5. Patrecia Daniela Butarbutar (23031030044)
  6. Nayli Kurnia Ilahi (23031030045)
  7. Nafisa Salsabila (23031030048)

DATA PENJUALAN Z8 (HT70) Jan 2015 - Jun 2017

periode <- c(
  "Jan-15","Feb-15","Mar-15","Apr-15","May-15","Jun-15",
  "Jul-15","Aug-15","Sep-15","Oct-15","Nov-15","Dec-15",
  "Jan-16","Feb-16","Mar-16","Apr-16","May-16","Jun-16",
  "Jul-16","Aug-16","Sep-16","Oct-16","Nov-16","Dec-16",
  "Jan-17","Feb-17","Mar-17","Apr-17","May-17","Jun-17"
)

penjualan <- c(
  66, 70, 69,  76, 85,  59,
  58, 109, 153,  70, 102, 62,
  76, 69, 74,  76,  85, 80,
  107,  83, 103, 107, 112, 83,
  78, 153, 53, 67, 63,  58
)

df <- data.frame(Periode = periode, Penjualan = penjualan)
knitr::kable(df, caption = "Tabel 1. Data Penjualan HT70 (Z8)", align = "c")
Tabel 1. Data Penjualan HT70 (Z8)
Periode Penjualan
Jan-15 66
Feb-15 70
Mar-15 69
Apr-15 76
May-15 85
Jun-15 59
Jul-15 58
Aug-15 109
Sep-15 153
Oct-15 70
Nov-15 102
Dec-15 62
Jan-16 76
Feb-16 69
Mar-16 74
Apr-16 76
May-16 85
Jun-16 80
Jul-16 107
Aug-16 83
Sep-16 103
Oct-16 107
Nov-16 112
Dec-16 83
Jan-17 78
Feb-17 153
Mar-17 53
Apr-17 67
May-17 63
Jun-17 58

TAHAP 1 PENENTUAN STATE ORDE SATU

State: P = 0 (naik/sama), K = 1 (turun) Bandingkan penjualan[t] vs penjualan[t-1]

n <- length(penjualan)

state_label <- ifelse(penjualan[2:n] >= penjualan[1:(n-1)], "P", "K")
state_val   <- ifelse(penjualan[2:n] >= penjualan[1:(n-1)],  0,   1)

df_state <- data.frame(
  Periode     = periode[2:n],
  Penjualan   = penjualan[2:n],
  Prev        = penjualan[1:(n-1)],
  Perubahan   = penjualan[2:n] - penjualan[1:(n-1)],
  State_Label = state_label,
  State_Val   = state_val
)

knitr::kable(df_state,
             col.names = c("Periode","Jual (t)","Jual (t-1)","Δ","State","Nilai"),
             caption   = "Tabel 2. Penentuan State Perbulan (Orde Satu)",
             align     = "c")
Tabel 2. Penentuan State Perbulan (Orde Satu)
Periode Jual (t) Jual (t-1) Δ State Nilai
Feb-15 70 66 4 P 0
Mar-15 69 70 -1 K 1
Apr-15 76 69 7 P 0
May-15 85 76 9 P 0
Jun-15 59 85 -26 K 1
Jul-15 58 59 -1 K 1
Aug-15 109 58 51 P 0
Sep-15 153 109 44 P 0
Oct-15 70 153 -83 K 1
Nov-15 102 70 32 P 0
Dec-15 62 102 -40 K 1
Jan-16 76 62 14 P 0
Feb-16 69 76 -7 K 1
Mar-16 74 69 5 P 0
Apr-16 76 74 2 P 0
May-16 85 76 9 P 0
Jun-16 80 85 -5 K 1
Jul-16 107 80 27 P 0
Aug-16 83 107 -24 K 1
Sep-16 103 83 20 P 0
Oct-16 107 103 4 P 0
Nov-16 112 107 5 P 0
Dec-16 83 112 -29 K 1
Jan-17 78 83 -5 K 1
Feb-17 153 78 75 P 0
Mar-17 53 153 -100 K 1
Apr-17 67 53 14 P 0
May-17 63 67 -4 K 1
Jun-17 58 63 -5 K 1

TAHAP 2 — MATRIKS FREKUENSI TRANSISI 2x2

Hitung berapa kali terjadi transisi

sv <- state_val   # panjang 29

frek2 <- matrix(0, nrow = 2, ncol = 2,
                dimnames = list(
                  c("dari_P","dari_K"),
                  c("ke_P",  "ke_K")
                ))

for (t in 1:(length(sv) - 1)) {
  i <- sv[t]   + 1   # baris  (1-based)
  j <- sv[t+1] + 1   # kolom  (1-based)
  frek2[i, j] <- frek2[i, j] + 1
}

knitr::kable(frek2,
             caption = "Tabel 3. Matriks Frekuensi Transisi f_ij (2×2)",
             align   = "c")
Tabel 3. Matriks Frekuensi Transisi f_ij (2×2)
ke_P ke_K
dari_P 6 10
dari_K 9 3

TAHAP 3 MATRIKS PROBABILITAS TRANSISI 2x2

P_ij = f_ij / jumlah baris i

row_sum2 <- rowSums(frek2)

prob2 <- matrix(0, nrow = 2, ncol = 2,
                dimnames = list(
                  c("P (Perolehan)","K (Kehilangan)"),
                  c("→ P","→ K")
                ))

for (i in 1:2) {
  if (row_sum2[i] > 0) {
    prob2[i, ] <- frek2[i, ] / row_sum2[i]
  }
}

knitr::kable(round(prob2, 4),
             caption = "Tabel 4. Matriks Probabilitas Transisi P (2×2)",
             align   = "c")
Tabel 4. Matriks Probabilitas Transisi P (2×2)
→ P → K
P (Perolehan) 0.375 0.625
K (Kehilangan) 0.750 0.250

TAHAP 4 ITERASI STEADY STATE

S(t+1) = S(t) · P hingga konvergen

S <- c(0.5, 0.5)   # vektor awal seragam

tol      <- 1e-8
max_iter <- 10000
history  <- list()

for (iter in 1:max_iter) {
  S_new <- as.numeric(S %*% prob2)
  
  if (iter <= 5 || iter %% 500 == 0) {
    history[[length(history) + 1]] <- c(iter = iter, round(S_new, 6))
  }
  
  if (max(abs(S_new - S)) < tol) {
    cat("Steady state tercapai pada iterasi ke:", iter, "\n")
    S <- S_new
    break
  }
  S <- S_new
}
## Steady state tercapai pada iterasi ke: 17
df_hist <- do.call(rbind, history)
df_hist <- as.data.frame(df_hist)
colnames(df_hist) <- c("Iterasi", "S_P", "S_K")
knitr::kable(df_hist,
             caption   = "Tabel 5. Riwayat Iterasi Menuju Steady State",
             align     = "c", row.names = FALSE)
Tabel 5. Riwayat Iterasi Menuju Steady State
Iterasi S_P S_K
1 0.562500 0.437500
2 0.539062 0.460938
3 0.547852 0.452148
4 0.544556 0.455444
5 0.545792 0.454208

TAHAP 5 HASIL STEADY STATE & PANGSA PASAR

cat("\n=== PANGSA PASAR HT70 (ORDE SATU) ===\n")
## 
## === PANGSA PASAR HT70 (ORDE SATU) ===
cat(sprintf("  Perolehan konsumen (P) : %.4f  (%.2f%%)\n", S[1], S[1]*100))
##   Perolehan konsumen (P) : 0.5455  (54.55%)
cat(sprintf("  Kehilangan konsumen (K): %.4f  (%.2f%%)\n", S[2], S[2]*100))
##   Kehilangan konsumen (K): 0.4545  (45.45%)
cat(sprintf("  Jumlah                 : %.4f\n", sum(S)))
##   Jumlah                 : 1.0000
df_ss <- data.frame(
  Kondisi      = c("Perolehan (P)","Kehilangan (K)"),
  Probabilitas = round(S, 4),
  Persentase   = paste0(round(S * 100, 2), "%")
)

knitr::kable(df_ss,
             caption = "Tabel 6. Pangsa Pasar HT70 — Steady State Orde Satu",
             align   = "c")
Tabel 6. Pangsa Pasar HT70 — Steady State Orde Satu
Kondisi Probabilitas Persentase
Perolehan (P) 0.5455 54.55%
Kehilangan (K) 0.4545 45.45%

TAHAP 6 PREDIKSI PENJUALAN JULI 2017

Prediksi = Jual(t) + Jual(t) × %P − Jual(t) × %K

jual_juni <- penjualan[length(penjualan)]   # Jun-17 = 58

prediksi_juli_o1 <- jual_juni + (jual_juni * S[1]) - (jual_juni * S[2])

cat("\n=== PREDIKSI PENJUALAN JULI 2017 (ORDE SATU) ===\n")
## 
## === PREDIKSI PENJUALAN JULI 2017 (ORDE SATU) ===
cat(sprintf("  Penjualan Juni 2017     : %d pcs\n",     jual_juni))
##   Penjualan Juni 2017     : 58 pcs
cat(sprintf("  %% Perolehan             : %.2f%%\n",     S[1]*100))
##   % Perolehan             : 54.55%
cat(sprintf("  %% Kehilangan            : %.2f%%\n",     S[2]*100))
##   % Kehilangan            : 45.45%
cat(sprintf("  Prediksi Juli 2017      : %.2f pcs ≈ %d pcs\n",
            prediksi_juli_o1, round(prediksi_juli_o1)))
##   Prediksi Juli 2017      : 63.27 pcs ≈ 63 pcs
df_pred <- data.frame(
  Keterangan = c(
    "Penjualan Juni 2017",
    "% Perolehan (P)",
    "% Kehilangan (K)",
    "Prediksi Juli 2017 (desimal)",
    "Prediksi Juli 2017 (dibulatkan)"
  ),
  Nilai = c(
    jual_juni,
    round(S[1] * 100, 2),
    round(S[2] * 100, 2),
    round(prediksi_juli_o1, 4),
    round(prediksi_juli_o1)
  )
)

knitr::kable(df_pred,
             caption = "Tabel 7. Ringkasan Prediksi Penjualan HT70 (Orde Satu)",
             align   = "c")
Tabel 7. Ringkasan Prediksi Penjualan HT70 (Orde Satu)
Keterangan Nilai
Penjualan Juni 2017 58.0000
% Perolehan (P) 54.5500
% Kehilangan (K) 45.4500
Prediksi Juli 2017 (desimal) 63.2727
Prediksi Juli 2017 (dibulatkan) 63.0000

##PLOT ORDE SATU: Data Historis + Prediksi + Pangsa Pasar

par(mfrow = c(1, 2), mar = c(5, 4, 4, 2))

# --- Plot 1: Time series + prediksi ---
plot(1:n, penjualan, type = "b", pch = 16, col = "steelblue",
     xlab = "Bulan ke-", ylab = "Penjualan (pcs)",
     main = "Penjualan HT70 (Z9) Jan 2015 – Jun 2017\n(Orde Satu)",
     xaxt = "n", lwd = 2)
axis(1, at = c(1, 7, 13, 19, 25, 30),
     labels = c("Jan-15","Jul-15","Jan-16","Jul-16","Jan-17","Jun-17"),
     cex.axis = 0.7)
points(n + 1, round(prediksi_juli_o1), pch = 17, col = "red", cex = 1.5)
lines(c(n, n + 1), c(jual_juni, round(prediksi_juli_o1)),
      lty = 2, col = "red", lwd = 2)
legend("topright",
       legend = c("Historis", "Prediksi Jul-17"),
       col = c("steelblue","red"), pch = c(16, 17),
       lty = c(1, 2), cex = 0.8)
abline(h = mean(penjualan), lty = 3, col = "gray50")
text(2, mean(penjualan) + 2,
     paste0("rata-rata = ", round(mean(penjualan), 1)),
     col = "gray40", cex = 0.75)

# --- Plot 2: Pangsa Pasar ---
barplot(S * 100,
        names.arg = c("Perolehan (P)", "Kehilangan (K)"),
        col  = c("steelblue", "tomato"),
        ylab = "Probabilitas (%)",
        main = "Pangsa Pasar HT70\n(Steady State Orde Satu)",
        ylim = c(0, 100))
text(0.7, S[1] * 100 + 3, paste0(round(S[1]*100, 2), "%"), cex = 0.9)
text(1.9, S[2] * 100 + 3, paste0(round(S[2]*100, 2), "%"), cex = 0.9)

ANALISIS RANTAI MARKOV ORDE DUA

cat("\n\n========================================\n")
## 
## 
## ========================================
cat("    ANALISIS RANTAI MARKOV ORDE DUA\n")
##     ANALISIS RANTAI MARKOV ORDE DUA
cat("========================================\n")
## ========================================

TAHAP 7 STATE GABUNGAN Y_t (ORDE DUA)

Y_t dibentuk dari pasangan (X(t-1), X(t)) PP=0, PK=1, KP=2, KK=3

Xt   <- sv[2:length(sv)]
Xt_1 <- sv[1:(length(sv) - 1)]

Y_val <- ifelse(Xt == 0 & Xt_1 == 0, 0,
                ifelse(Xt == 0 & Xt_1 == 1, 1,
                       ifelse(Xt == 1 & Xt_1 == 0, 2, 3)))

Y_label <- c("PP","PK","KP","KK")[Y_val + 1]

df_Y <- data.frame(
  t        = 2:length(sv),
  Periode  = periode[3:n],
  Xt_1_val = Xt_1,
  Xt_val   = Xt,
  Y_val    = Y_val,
  Y_label  = Y_label
)

knitr::kable(df_Y,
             col.names = c("t","Periode","X(t-1)","X(t)","Y_t","Label"),
             caption   = "Tabel 8. State Gabungan Y_t (Orde Dua)",
             align     = "c")
Tabel 8. State Gabungan Y_t (Orde Dua)
t Periode X(t-1) X(t) Y_t Label
2 Mar-15 0 1 2 KP
3 Apr-15 1 0 1 PK
4 May-15 0 0 0 PP
5 Jun-15 0 1 2 KP
6 Jul-15 1 1 3 KK
7 Aug-15 1 0 1 PK
8 Sep-15 0 0 0 PP
9 Oct-15 0 1 2 KP
10 Nov-15 1 0 1 PK
11 Dec-15 0 1 2 KP
12 Jan-16 1 0 1 PK
13 Feb-16 0 1 2 KP
14 Mar-16 1 0 1 PK
15 Apr-16 0 0 0 PP
16 May-16 0 0 0 PP
17 Jun-16 0 1 2 KP
18 Jul-16 1 0 1 PK
19 Aug-16 0 1 2 KP
20 Sep-16 1 0 1 PK
21 Oct-16 0 0 0 PP
22 Nov-16 0 0 0 PP
23 Dec-16 0 1 2 KP
24 Jan-17 1 1 3 KK
25 Feb-17 1 0 1 PK
26 Mar-17 0 1 2 KP
27 Apr-17 1 0 1 PK
28 May-17 0 1 2 KP
29 Jun-17 1 1 3 KK

TAHAP 8 MATRIKS FREKUENSI TRANSISI 4x4

frek <- matrix(0, nrow = 4, ncol = 4,
               dimnames = list(
                 paste0("dari_", c("PP","PK","KP","KK")),
                 paste0("ke_",   c("PP","PK","KP","KK"))
               ))

for (t in 1:(length(Y_val) - 1)) {
  i <- Y_val[t]     + 1
  j <- Y_val[t + 1] + 1
  frek[i, j] <- frek[i, j] + 1
}

knitr::kable(frek,
             caption = "Tabel 9. Matriks Frekuensi Transisi f_ij (4×4)",
             align   = "c")
Tabel 9. Matriks Frekuensi Transisi f_ij (4×4)
ke_PP ke_PK ke_KP ke_KK
dari_PP 2 0 4 0
dari_PK 4 0 5 0
dari_KP 0 7 0 3
dari_KK 0 2 0 0

TAHAP 9 MATRIKS PROBABILITAS TRANSISI 4x4

row_sum <- rowSums(frek)

prob <- matrix(0, nrow = 4, ncol = 4,
               dimnames = list(
                 c("PP","PK","KP","KK"),
                 c("PP","PK","KP","KK")
               ))

for (i in 1:4) {
  if (row_sum[i] > 0) {
    prob[i, ] <- frek[i, ] / row_sum[i]
  }
}

knitr::kable(round(prob, 4),
             caption = "Tabel 10. Matriks Probabilitas Transisi P (4×4)",
             align   = "c")
Tabel 10. Matriks Probabilitas Transisi P (4×4)
PP PK KP KK
PP 0.3333 0.0 0.6667 0.0
PK 0.4444 0.0 0.5556 0.0
KP 0.0000 0.7 0.0000 0.3
KK 0.0000 1.0 0.0000 0.0

TAHAP 10 ITERASI STEADY STATE ORDE DUA

S2 <- c(0.25, 0.25, 0.25, 0.25)

history2 <- list()

for (iter in 1:max_iter) {
  S2_new <- as.numeric(S2 %*% prob)
  
  if (iter <= 5 || iter %% 500 == 0) {
    history2[[length(history2) + 1]] <- c(iter = iter, round(S2_new, 6))
  }
  
  if (max(abs(S2_new - S2)) < tol) {
    cat("Steady state orde dua tercapai pada iterasi ke:", iter, "\n")
    S2 <- S2_new
    break
  }
  S2 <- S2_new
}
## Steady state orde dua tercapai pada iterasi ke: 22
df_hist2 <- as.data.frame(do.call(rbind, history2))
colnames(df_hist2) <- c("Iterasi", "S_PP", "S_PK", "S_KP", "S_KK")
knitr::kable(df_hist2,
             caption   = "Tabel 11. Riwayat Iterasi Menuju Steady State (Orde Dua)",
             align     = "c", row.names = FALSE)
Tabel 11. Riwayat Iterasi Menuju Steady State (Orde Dua)
Iterasi S_PP S_PK S_KP S_KK
1 0.194444 0.425000 0.305556 0.075000
2 0.253704 0.288889 0.365741 0.091667
3 0.212963 0.347685 0.329630 0.109722
4 0.225514 0.340463 0.335134 0.098889
5 0.226488 0.333483 0.339489 0.100540
cat("\nHASIL STEADY STATE ORDE DUA\n")
## 
## HASIL STEADY STATE ORDE DUA
cat(sprintf("  P_0 (PP) = %.4f\n", S2[1]))
##   P_0 (PP) = 0.2247
cat(sprintf("  P_1 (PK) = %.4f\n", S2[2]))
##   P_1 (PK) = 0.3371
cat(sprintf("  P_2 (KP) = %.4f\n", S2[3]))
##   P_2 (KP) = 0.3371
cat(sprintf("  P_3 (KK) = %.4f\n", S2[4]))
##   P_3 (KK) = 0.1011
cat(sprintf("  Jumlah   = %.4f\n", sum(S2)))
##   Jumlah   = 1.0000
df_ss2 <- data.frame(
  State        = c("0-PP","1-PK","2-KP","3-KK"),
  Probabilitas = round(S2, 4)
)
knitr::kable(df_ss2,
             caption = "Tabel 12. Probabilitas Steady State HT70 (Orde Dua)",
             align   = "c")
Tabel 12. Probabilitas Steady State HT70 (Orde Dua)
State Probabilitas
0-PP 0.2247
1-PK 0.3371
2-KP 0.3371
3-KK 0.1011

TAHAP 11 REDUKSI ORDE DUA ORDE SATU

Frekuensi stabil dari steady state × total transisi

total_trans <- sum(frek)
f_stabil    <- round(S2 * total_trans)
names(f_stabil) <- c("PP","PK","KP","KK")

cat("Total transisi yang diamati:", total_trans, "\n\n")
## Total transisi yang diamati: 27
df_fstab <- data.frame(
  State            = c("PP (f00)","PK (f01)","KP (f10)","KK (f11)"),
  Frekuensi_Stabil = f_stabil
)
knitr::kable(df_fstab,
             caption   = "Tabel 13. Frekuensi di Kondisi Stabil (Orde Dua ke Orde Satu)",
             align     = "c", row.names = FALSE)
Tabel 13. Frekuensi di Kondisi Stabil (Orde Dua ke Orde Satu)
State Frekuensi_Stabil
PP (f00) 6
PK (f01) 9
KP (f10) 9
KK (f11) 3

TAHAP 12 MATRIKS PROBABILITAS TRANSISI BARU (2x2)

f00 <- f_stabil["PP"];  f01 <- f_stabil["PK"]
f10 <- f_stabil["KP"];  f11 <- f_stabil["KK"]

mat_baru <- matrix(
  c(f00/(f00+f01), f01/(f00+f01),
    f10/(f10+f11), f11/(f10+f11)),
  nrow = 2, byrow = TRUE,
  dimnames = list(c("P (Perolehan)","K (Kehilangan)"),
                  c("→ P","→ K"))
)

knitr::kable(round(mat_baru, 4),
             caption = "Tabel 14. Matriks Probabilitas Transisi Baru (2×2)",
             align   = "c")
Tabel 14. Matriks Probabilitas Transisi Baru (2×2)
→ P → K
P (Perolehan) 0.40 0.60
K (Kehilangan) 0.75 0.25

TAHAP 13 STEADY STATE 2x2 PANGSA PASAR ORDE DUA

S3 <- c(0.5, 0.5)

for (iter in 1:max_iter) {
  S3_new <- as.numeric(S3 %*% mat_baru)
  if (max(abs(S3_new - S3)) < tol) break
  S3 <- S3_new
}

cat("=== PANGSA PASAR HT70 (ORDE DUA) ===\n")
## === PANGSA PASAR HT70 (ORDE DUA) ===
cat(sprintf("  Perolehan konsumen (P) : %.4f  (%.2f%%)\n", S3[1], S3[1]*100))
##   Perolehan konsumen (P) : 0.5556  (55.56%)
cat(sprintf("  Kehilangan konsumen (K): %.4f  (%.2f%%)\n", S3[2], S3[2]*100))
##   Kehilangan konsumen (K): 0.4444  (44.44%)
df_ms <- data.frame(
  Kondisi      = c("Perolehan (P)","Kehilangan (K)"),
  Probabilitas = round(S3, 4),
  Persentase   = paste0(round(S3 * 100, 2), "%")
)
knitr::kable(df_ms,
             caption = "Tabel 15. Pangsa Pasar HT70 (Steady State Orde Dua)",
             align   = "c")
Tabel 15. Pangsa Pasar HT70 (Steady State Orde Dua)
Kondisi Probabilitas Persentase
Perolehan (P) 0.5556 55.56%
Kehilangan (K) 0.4444 44.44%

TAHAP 14 PREDIKSI PENJUALAN JULI 2017 (ORDE DUA)

prediksi_juli_o2 <- jual_juni + (jual_juni * S3[1]) - (jual_juni * S3[2])

cat("=== PREDIKSI PENJUALAN JULI 2017 (ORDE DUA) ===\n")
## === PREDIKSI PENJUALAN JULI 2017 (ORDE DUA) ===
cat(sprintf("  Penjualan Juni 2017     : %d pcs\n",     jual_juni))
##   Penjualan Juni 2017     : 58 pcs
cat(sprintf("  %% Perolehan             : %.2f%%\n",     S3[1]*100))
##   % Perolehan             : 55.56%
cat(sprintf("  %% Kehilangan            : %.2f%%\n",     S3[2]*100))
##   % Kehilangan            : 44.44%
cat(sprintf("  Prediksi Juli 2017      : %.2f pcs ≈ %d pcs\n",
            prediksi_juli_o2, round(prediksi_juli_o2)))
##   Prediksi Juli 2017      : 64.44 pcs ≈ 64 pcs
df_pred2 <- data.frame(
  Keterangan = c(
    "Penjualan Juni 2017",
    "% Perolehan (P)",
    "% Kehilangan (K)",
    "Prediksi Juli 2017 (desimal)",
    "Prediksi Juli 2017 (dibulatkan)"
  ),
  Nilai = c(
    jual_juni,
    round(S3[1] * 100, 2),
    round(S3[2] * 100, 2),
    round(prediksi_juli_o2, 4),
    round(prediksi_juli_o2)
  )
)
knitr::kable(df_pred2,
             caption = "Tabel 16. Ringkasan Prediksi Penjualan HT70 (Orde Dua)",
             align   = "c")
Tabel 16. Ringkasan Prediksi Penjualan HT70 (Orde Dua)
Keterangan Nilai
Penjualan Juni 2017 58.0000
% Perolehan (P) 55.5600
% Kehilangan (K) 44.4400
Prediksi Juli 2017 (desimal) 64.4444
Prediksi Juli 2017 (dibulatkan) 64.0000

TABEL PERBANDINGAN ORDE SATU vs ORDE DUA

df_compare <- data.frame(
  Keterangan = c("% Perolehan (P)",
                 "% Kehilangan (K)",
                 "Prediksi Juli 2017 (pcs)"),
  Orde_Satu  = c(paste0(round(S[1]*100, 2), "%"),
                 paste0(round(S[2]*100, 2), "%"),
                 as.character(round(prediksi_juli_o1))),
  Orde_Dua   = c(paste0(round(S3[1]*100, 2), "%"),
                 paste0(round(S3[2]*100, 2), "%"),
                 as.character(round(prediksi_juli_o2)))
)
knitr::kable(df_compare,
             caption = "Tabel 17. Perbandingan Hasil Orde Satu vs Orde Dua",
             align   = "c")
Tabel 17. Perbandingan Hasil Orde Satu vs Orde Dua
Keterangan Orde_Satu Orde_Dua
% Perolehan (P) 54.55% 55.56%
% Kehilangan (K) 45.45% 44.44%
Prediksi Juli 2017 (pcs) 63 64

PLOT ORDE DUA: Data Historis + Prediksi + Pangsa Pasar

par(mfrow = c(1, 2), mar = c(5, 4, 4, 2))

# --- Plot 1: Time series + prediksi ---
plot(1:n, penjualan, type = "b", pch = 16, col = "steelblue",
     xlab = "Bulan ke-", ylab = "Penjualan (pcs)",
     main = "Penjualan HT70 (Z9) Jan 2015 – Jun 2017\n(Orde Dua)",
     xaxt = "n", lwd = 2)
axis(1, at = c(1, 7, 13, 19, 25, 30),
     labels = c("Jan-15","Jul-15","Jan-16","Jul-16","Jan-17","Jun-17"),
     cex.axis = 0.7)
points(n + 1, round(prediksi_juli_o2), pch = 17, col = "darkgreen", cex = 1.5)
lines(c(n, n + 1), c(jual_juni, round(prediksi_juli_o2)),
      lty = 2, col = "darkgreen", lwd = 2)
legend("topright",
       legend = c("Historis", "Prediksi Jul-17"),
       col = c("steelblue","darkgreen"), pch = c(16, 17),
       lty = c(1, 2), cex = 0.8)
abline(h = mean(penjualan), lty = 3, col = "gray50")
text(2, mean(penjualan) + 2,
     paste0("rata-rata = ", round(mean(penjualan), 1)),
     col = "gray40", cex = 0.75)

# --- Plot 2: Pangsa Pasar ---
barplot(S3 * 100,
        names.arg = c("Perolehan (P)", "Kehilangan (K)"),
        col  = c("steelblue", "tomato"),
        ylab = "Probabilitas (%)",
        main = "Pangsa Pasar HT70\n(Steady State Orde Dua)",
        ylim = c(0, 100))
text(0.7, S3[1] * 100 + 3, paste0(round(S3[1]*100, 2), "%"), cex = 0.9)
text(1.9, S3[2] * 100 + 3, paste0(round(S3[2]*100, 2), "%"), cex = 0.9)

DATA PENJUALAN NB170

Data penjualan bulanan DOVE SHP NOURISHING BLACK 170 ML (NB170) selama 30 periode dari Januari 2015 hingga Juni 2017 di Swalayan Pamella 1, Yogyakarta. Catatan: nilai Oktober 2015 (Oct-15) = 0.

# DATA PENJUALAN (NB170) Jan 2015 - Jun 2017
periode <- c(
  "Jan-15","Feb-15","Mar-15","Apr-15","May-15","Jun-15",
  "Jul-15","Aug-15","Sep-15","Oct-15","Nov-15","Dec-15",
  "Jan-16","Feb-16","Mar-16","Apr-16","May-16","Jun-16",
  "Jul-16","Aug-16","Sep-16","Oct-16","Nov-16","Dec-16",
  "Jan-17","Feb-17","Mar-17","Apr-17","May-17","Jun-17"
)

penjualan <- c(
  21, 22, 18,  17,  20,  24,   # 2015 Jan-Jun
  10,  30, 28,  28,  14, 21,   # 2015 Jul-Dec  
  26, 31, 29,  36,  29, 22,  # 2016 Jan-Jun
  26,  17, 25, 20, 15, 23,  # 2016 Jul-Dec
  18,  16, 30, 17, 18,  12   # 2017 Jan-Jun
)

df <- data.frame(Periode = periode, Penjualan = penjualan)
knitr::kable(df, caption = "Tabel 1. Data Penjualan NB170", align = "c")
Tabel 1. Data Penjualan NB170
Periode Penjualan
Jan-15 21
Feb-15 22
Mar-15 18
Apr-15 17
May-15 20
Jun-15 24
Jul-15 10
Aug-15 30
Sep-15 28
Oct-15 28
Nov-15 14
Dec-15 21
Jan-16 26
Feb-16 31
Mar-16 29
Apr-16 36
May-16 29
Jun-16 22
Jul-16 26
Aug-16 17
Sep-16 25
Oct-16 20
Nov-16 15
Dec-16 23
Jan-17 18
Feb-17 16
Mar-17 30
Apr-17 17
May-17 18
Jun-17 12

Penentuan State (Perolehan / Kehilangan)

State \(X\_t\) ditentukan berdasarkan perubahan penjualan bulan ke-\(t\) dibanding bulan ke-\((t-1)\).

Jika penjualan mengalami peningkatan atau tetap, maka dikategorikan sebagai Perolehan (P).
Sebaliknya, jika penjualan mengalami penurunan, maka dikategorikan sebagai Kehilangan (K).

Secara matematis, state dapat dituliskan sebagai berikut:

\[ X\_t = \begin{cases} 0 \; (P = \text{Perolehan}), & \text{jika penjualan naik atau sama} \\ 1 \; (K = \text{Kehilangan}), & \text{jika penjualan turun} \end{cases} \]

Berdasarkan data penjualan yang digunakan, perubahan dari bulan ke bulan kemudian diklasifikasikan ke dalam dua state tersebut. Hasil klasifikasi ini akan digunakan untuk membentuk urutan state yang menjadi dasar dalam analisis rantai Markov orde dua.

# TENTUKAN STATE: 
# P = 0 (naik atau sama), K = 1 (turun)

n <- length(penjualan)

# Bandingkan bulan t dengan t-1
state_label <- ifelse(penjualan[2:n] >= penjualan[1:(n-1)], "P", "K")
state_val   <- ifelse(penjualan[2:n] >= penjualan[1:(n-1)], 0, 1)

# Data frame hasil
df_state <- data.frame(
  Periode     = periode[2:n],
  Penjualan_t = penjualan[2:n],
  Penjualan_t1= penjualan[1:(n-1)],
  Perubahan   = penjualan[2:n] - penjualan[1:(n-1)],
  State       = state_label,
  Nilai       = state_val
)

# Tampilkan tabel
knitr::kable(
  df_state,
  col.names = c("Periode","Jual (t)","Jual (t-1)","Δ","State","Nilai"),
  caption   = "Tabel 2. Penentuan State Perubahan Penjualan NB170",
  align     = "c"
)
Tabel 2. Penentuan State Perubahan Penjualan NB170
Periode Jual (t) Jual (t-1) Δ State Nilai
Feb-15 22 21 1 P 0
Mar-15 18 22 -4 K 1
Apr-15 17 18 -1 K 1
May-15 20 17 3 P 0
Jun-15 24 20 4 P 0
Jul-15 10 24 -14 K 1
Aug-15 30 10 20 P 0
Sep-15 28 30 -2 K 1
Oct-15 28 28 0 P 0
Nov-15 14 28 -14 K 1
Dec-15 21 14 7 P 0
Jan-16 26 21 5 P 0
Feb-16 31 26 5 P 0
Mar-16 29 31 -2 K 1
Apr-16 36 29 7 P 0
May-16 29 36 -7 K 1
Jun-16 22 29 -7 K 1
Jul-16 26 22 4 P 0
Aug-16 17 26 -9 K 1
Sep-16 25 17 8 P 0
Oct-16 20 25 -5 K 1
Nov-16 15 20 -5 K 1
Dec-16 23 15 8 P 0
Jan-17 18 23 -5 K 1
Feb-17 16 18 -2 K 1
Mar-17 30 16 14 P 0
Apr-17 17 30 -13 K 1
May-17 18 17 1 P 0
Jun-17 12 18 -6 K 1

Rantai Markov Orde Dua

State Gabungan Y_t Orde

Untuk rantai Markov orde dua, state gabungan \(Y\_t\) dibentuk berdasarkan dua state sebelumnya, yaitu \((X\_t, X\_{t-1})\).

Karena setiap \(X\_t\) hanya memiliki dua kemungkinan, yaitu: - 0 = Perolehan (P) - 1 = Kehilangan (K)

Maka kombinasi state yang mungkin adalah sebagai berikut:

\(Y\_t\) \(X\_t\) \(X\_{t-1}\) Kode
0 0 (P) 0 (P) PP
1 0 (P) 1 (K) PK
2 1 (K) 0 (P) KP
3 1 (K) 1 (K) KK

State gabungan ini digunakan untuk merepresentasikan dinamika perubahan penjualan berdasarkan dua periode sebelumnya, sehingga dapat menangkap pola yang lebih kompleks dibandingkan rantai Markov orde satu.

sv <- state_val   # panjang = 29

# Ambil pasangan (X(t-1), X(t))
Xt_1 <- sv[1:(length(sv)-1)]   # 1..28
Xt   <- sv[2:length(sv)]       # 2..29

# Bentuk state gabungan
Y_val <- ifelse(Xt == 0 & Xt_1 == 0, 0,
                ifelse(Xt == 0 & Xt_1 == 1, 1,
                       ifelse(Xt == 1 & Xt_1 == 0, 2, 3)))

Y_label <- c("PP","PK","KP","KK")[Y_val + 1]

# Periode harus mulai dari bulan ke-3
df_Y <- data.frame(
  t        = 3:length(penjualan),   # karena mulai dari pasangan ke-2
  Periode  = periode[3:length(penjualan)],
  Xt_1_val = Xt_1,
  Xt_val   = Xt,
  Y_val    = Y_val,
  Y_label  = Y_label
)

# Tampilkan
knitr::kable(
  df_Y,
  col.names = c("t","Periode","X(t-1)","X(t)","Y_t","Label"),
  caption   = "Tabel 3. State Gabungan Y_t (Orde Dua) NB170",
  align     = "c"
)
Tabel 3. State Gabungan Y_t (Orde Dua) NB170
t Periode X(t-1) X(t) Y_t Label
3 Mar-15 0 1 2 KP
4 Apr-15 1 1 3 KK
5 May-15 1 0 1 PK
6 Jun-15 0 0 0 PP
7 Jul-15 0 1 2 KP
8 Aug-15 1 0 1 PK
9 Sep-15 0 1 2 KP
10 Oct-15 1 0 1 PK
11 Nov-15 0 1 2 KP
12 Dec-15 1 0 1 PK
13 Jan-16 0 0 0 PP
14 Feb-16 0 0 0 PP
15 Mar-16 0 1 2 KP
16 Apr-16 1 0 1 PK
17 May-16 0 1 2 KP
18 Jun-16 1 1 3 KK
19 Jul-16 1 0 1 PK
20 Aug-16 0 1 2 KP
21 Sep-16 1 0 1 PK
22 Oct-16 0 1 2 KP
23 Nov-16 1 1 3 KK
24 Dec-16 1 0 1 PK
25 Jan-17 0 1 2 KP
26 Feb-17 1 1 3 KK
27 Mar-17 1 0 1 PK
28 Apr-17 0 1 2 KP
29 May-17 1 0 1 PK
30 Jun-17 0 1 2 KP

Matriks Frekuensi Transisi Orde Dua

Frekuensi transisi \(f\_{ij}\) dihitung berdasarkan banyaknya perpindahan dari state gabungan \(Y\_t\) ke \(Y\_{t+1}\).

Setiap elemen \(f\_{ij}\) menyatakan jumlah kejadian ketika sistem berada pada state \(Y\_t = i\) dan berpindah ke state \(Y\_{t+1} = j\) pada periode berikutnya.

Proses perhitungan dilakukan dengan mengamati urutan state gabungan yang telah diperoleh, kemudian menghitung jumlah transisi antar state secara berurutan.

Secara matematis, frekuensi transisi dapat dituliskan sebagai:

\[ f\_{ij} = \text{jumlah transisi dari } Y\_t = i \text{ ke } Y\_{t+1} = j \]

Hasil perhitungan frekuensi transisi ini kemudian disusun dalam bentuk matriks frekuensi transisi orde dua, yang akan digunakan untuk menentukan matriks probabilitas transisi.

# FREKUENSI TRANSISI f_ij (Y_t → Y_{t+1})

states_label <- c("PP","PK","KP","KK")

frek <- matrix(0, nrow = 4, ncol = 4,
               dimnames = list(
                 paste0("dari_", states_label),
                 paste0("ke_",   states_label)
               ))

# Hitung transisi
for (t in 1:(length(Y_val) - 1)) {
  i <- Y_val[t]   + 1   # baris
  j <- Y_val[t+1] + 1   # kolom
  frek[i, j] <- frek[i, j] + 1
}

# Tampilkan tabel
knitr::kable(
  frek,
  caption = "Tabel 4. Matriks Frekuensi Transisi f_ij (Orde Dua) NB170",
  align   = "c"
)
Tabel 4. Matriks Frekuensi Transisi f_ij (Orde Dua) NB170
ke_PP ke_PK ke_KP ke_KK
dari_PP 1 0 2 0
dari_PK 2 0 8 0
dari_KP 0 6 0 4
dari_KK 0 4 0 0

Matriks Probabilitas Transisi Orde Dua

Probabilitas transisi \(P\_{ij}\) diperoleh dari normalisasi matriks frekuensi transisi \(f\_{ij}\).

Setiap elemen \(P\_{ij}\) menyatakan peluang berpindah dari state gabungan \(Y\_t = i\) ke \(Y\_{t+1} = j\), yang dihitung dengan membagi frekuensi transisi terhadap total frekuensi dari state asal \(i\).

Secara matematis, probabilitas transisi dirumuskan sebagai:

\[ P\_{ij} = \frac{f\_{ij}}{\sum\_{j=0}^{3} f\_{ij}} \]

dengan: - \(f\_{ij}\) = frekuensi transisi dari state \(i\) ke state \(j\) - \(\sum\_{j=0}^{3} f\_{ij}\) = total transisi yang berasal dari state \(i\)

Berdasarkan data yang digunakan, setiap baris pada matriks probabilitas transisi merupakan hasil pembagian nilai frekuensi transisi dengan jumlah total transisi pada baris tersebut, sehingga jumlah setiap baris pada matriks \(P\_{ij}\) bernilai 1.

# MATRIKS PROBABILITAS TRANSISI P

states_label <- c("PP","PK","KP","KK")

row_sum <- rowSums(frek)

prob <- matrix(0, nrow = 4, ncol = 4,
               dimnames = list(states_label, states_label))

# Hitung probabilitas
for (i in 1:4) {
  if (row_sum[i] > 0) {
    prob[i, ] <- frek[i, ] / row_sum[i]
  }
}

# Tampilkan
knitr::kable(
  round(prob, 4),
  caption = "Tabel 5. Matriks Probabilitas Transisi P (Orde Dua) NB170",
  align   = "c"
)
Tabel 5. Matriks Probabilitas Transisi P (Orde Dua) NB170
PP PK KP KK
PP 0.3333 0.0 0.6667 0.0
PK 0.2000 0.0 0.8000 0.0
KP 0.0000 0.6 0.0000 0.4
KK 0.0000 1.0 0.0000 0.0

Probabilitas Steady State

Probabilitas steady state diperoleh melalui proses iterasi menggunakan matriks probabilitas transisi \(P\).

Metode yang digunakan adalah sebagai berikut:

\[ S(t) = S(0) \cdot P \]

dengan: - \(S(t)\) = vektor probabilitas pada iterasi ke-\(t\) - \(S(0)\) = vektor probabilitas awal - \(P\) = matriks probabilitas transisi

Pada penelitian ini, digunakan vektor probabilitas awal yang bersifat seragam karena tidak ada informasi awal yang lebih spesifik, yaitu:

\[ S(0) = [0.25 \;\; 0.25 \;\; 0.25 \;\; 0.25] \]

yang merepresentasikan peluang awal untuk masing-masing state gabungan: - PP - PK - KP - KK

Proses iterasi dilakukan secara berulang hingga nilai \(S(t)\) konvergen (tidak mengalami perubahan signifikan). Nilai konvergen tersebut merupakan probabilitas steady state, yang menunjukkan distribusi jangka panjang dari masing-masing state dalam sistem.

# STEADY STATE  S(t) = S(0) · P

states_label <- c("PP","PK","KP","KK")

# Distribusi awal (boleh bebas, biasanya merata)
S <- c(0.25, 0.25, 0.25, 0.25)

tol      <- 1e-8
max_iter <- 10000
history  <- list()

for (iter in 1:max_iter) {
  S_new <- S %*% prob
  S_new <- as.numeric(S_new)
  
  # Simpan beberapa iterasi awal + interval
  if (iter <= 5 || iter %% 500 == 0) {
    history[[length(history) + 1]] <- c(iter, round(S_new, 6))
  }
  
  # Cek konvergensi
  if (max(abs(S_new - S)) < tol) {
    cat("Steady state tercapai pada iterasi ke:", iter, "\n")
    S <- S_new
    break
  }
  
  S <- S_new
}
## Steady state tercapai pada iterasi ke: 31
# Data frame hasil iterasi
df_hist <- do.call(rbind, history)
df_hist <- as.data.frame(df_hist)
colnames(df_hist) <- c("Iterasi", "S_PP", "S_PK", "S_KP", "S_KK")

knitr::kable(
  df_hist,
  caption = "Tabel 6. Riwayat Iterasi Menuju Steady State NB170",
  align   = "c",
  row.names = FALSE
)
Tabel 6. Riwayat Iterasi Menuju Steady State NB170
Iterasi S_PP S_PK S_KP S_KK
1 0.133333 0.400000 0.366667 0.100000
2 0.124444 0.320000 0.408889 0.146667
3 0.105481 0.392000 0.338963 0.163556
4 0.113560 0.366933 0.383921 0.135585
5 0.111240 0.365938 0.369254 0.153568
# Tampilkan steady state akhir
steady_state <- round(S, 6)
names(steady_state) <- states_label
steady_state
##       PP       PK       KP       KK 
## 0.111111 0.370370 0.370370 0.148148
# TAMPILKAN STEADY STATE
cat("Probabilitas Steady State (NB170):\n")
## Probabilitas Steady State (NB170):
cat(sprintf("  P_0 (PP) = %.4f\n", S[1]))
##   P_0 (PP) = 0.1111
cat(sprintf("  P_1 (PK) = %.4f\n", S[2]))
##   P_1 (PK) = 0.3704
cat(sprintf("  P_2 (KP) = %.4f\n", S[3]))
##   P_2 (KP) = 0.3704
cat(sprintf("  P_3 (KK) = %.4f\n", S[4]))
##   P_3 (KK) = 0.1481
cat(sprintf("  Jumlah   = %.4f\n", sum(S)))
##   Jumlah   = 1.0000
# Tabel
df_ss <- data.frame(
  State        = c("0 - PP","1 - PK","2 - KP","3 - KK"),
  Probabilitas = round(S, 4)
)

knitr::kable(
  df_ss,
  caption = "Tabel 7. Probabilitas Steady State NB170",
  align   = "c"
)
Tabel 7. Probabilitas Steady State NB170
State Probabilitas
0 - PP 0.1111
1 - PK 0.3704
2 - KP 0.3704
3 - KK 0.1481

Pangsa Pasar (Market Share)

Berdasarkan vektor probabilitas steady state yang telah diperoleh:

\[ S(n) = [P\_{n0}, P\_{n1}, P\_{n2}, P\_{n3}] \]

yang masing-masing merepresentasikan probabilitas untuk state gabungan: - \(P\_{n0}\) = PP
- \(P\_{n1}\) = PK
- \(P\_{n2}\) = KP
- \(P\_{n3}\) = KK

Jumlah kejadian perpindahan pada kondisi stabil dapat dihitung dengan mengalikan probabilitas steady state dengan total frekuensi transisi yang diamati.

Secara matematis dirumuskan sebagai:

\[ f\_{ij}^{stabil} = S(n)\_i \times (\text{total frekuensi}) \]

dengan: - \(f\_{ij}^{stabil}\) = jumlah kejadian pada kondisi stabil dari state \(i\) - \(S(n)\_i\) = probabilitas steady state pada state ke-\(i\) - total frekuensi = jumlah seluruh transisi pada data

Nilai ini menggambarkan estimasi jumlah kejadian perpindahan antar state dalam jangka panjang, ketika sistem telah mencapai kondisi stabil.

Hasil perhitungan ini selanjutnya digunakan untuk menentukan pangsa pasar (market share) dari masing-masing kondisi, sehingga dapat diketahui dominasi pola perubahan penjualan dalam jangka panjang.

# FREKUENSI KONDISI STABIL

# Total transisi (dari matriks frek)
total_trans <- sum(frek)

cat("Total transisi yang diamati:", total_trans, "\n\n")
## Total transisi yang diamati: 27
# Frekuensi stabil (dibulatkan)
f_stabil <- round(S * total_trans)
names(f_stabil) <- c("PP","PK","KP","KK")

# Tabel hasil
df_fstab <- data.frame(
  State = c("PP (f00)","PK (f01)","KP (f10)","KK (f11)"),
  Frekuensi_Stabil = f_stabil
)

knitr::kable(
  df_fstab,
  caption = "Tabel 8. Frekuensi Kondisi Stabil NB170 (Orde Dua)",
  align   = "c",
  row.names = FALSE
)
Tabel 8. Frekuensi Kondisi Stabil NB170 (Orde Dua)
State Frekuensi_Stabil
PP (f00) 3
PK (f01) 10
KP (f10) 10
KK (f11) 4

Matriks Probabilitas Transisi Baru (2×2)

Setelah diperoleh matriks frekuensi transisi pada state gabungan (PP, PK, KP, KK), analisis kemudian direduksi kembali ke dua kondisi utama, yaitu Perolehan (P) dan Kehilangan (K).

Reduksi ini dilakukan dengan mengelompokkan state gabungan berdasarkan state saat ini (\(X\_t\)), sehingga diperoleh matriks probabilitas transisi baru berukuran 2×2.

Secara matematis, matriks probabilitas transisi baru dirumuskan sebagai:

\[ P\_{\text{new}} = \begin{bmatrix} \frac{f\_{PP}}{f\_{PP} + f\_{PK}} & \frac{f\_{PK}}{f\_{PP} + f\_{PK}} \\ \frac{f\_{KP}}{f\_{KP} + f\_{KK}} & \frac{f\_{KK}}{f\_{KP} + f\_{KK}} \end{bmatrix} \]

dengan: - \(f\_{PP}\) = frekuensi transisi dari P ke P
- \(f\_{PK}\) = frekuensi transisi dari P ke K
- \(f\_{KP}\) = frekuensi transisi dari K ke P
- \(f\_{KK}\) = frekuensi transisi dari K ke K

Baris pertama menunjukkan probabilitas transisi dari kondisi Perolehan (P), sedangkan baris kedua menunjukkan probabilitas transisi dari kondisi Kehilangan (K).

Matriks ini memberikan gambaran yang lebih sederhana mengenai dinamika perpindahan antara kondisi perolehan dan kehilangan dalam sistem.

# Matriks Probabilitas Transisi Baru (2×2)

f00 <- f_stabil["PP"];  f01 <- f_stabil["PK"]
f10 <- f_stabil["KP"];  f11 <- f_stabil["KK"]

# Baris P
P00_new <- f00 / (f00 + f01)
P01_new <- f01 / (f00 + f01)

# Baris K (antisipasi pembagi nol)
if ((f10 + f11) == 0) {
  P10_new <- 0
  P11_new <- 0
} else {
  P10_new <- f10 / (f10 + f11)
  P11_new <- f11 / (f10 + f11)
}

# Matriks
mat_baru <- matrix(
  c(P00_new, P01_new,
    P10_new, P11_new),
  nrow = 2, byrow = TRUE,
  dimnames = list(c("P (Perolehan)","K (Kehilangan)"),
                  c("→ P","→ K"))
)

knitr::kable(
  round(mat_baru, 4),
  caption = "Tabel 9. Matriks Probabilitas Transisi Baru (2×2) NB170",
  align   = "c"
)
Tabel 9. Matriks Probabilitas Transisi Baru (2×2) NB170
→ P → K
P (Perolehan) 0.2308 0.7692
K (Kehilangan) 0.7143 0.2857

Steady State 2×2 (Pangsa Pasar)

# Steady State 2×2 (Pangsa Pasar)
# Salin matriks baru
P2 <- mat_baru

# Perbaiki jika ada baris nol (tidak terdefinisi)
for (i in 1:nrow(P2)) {
  if (sum(P2[i, ]) == 0) {
    P2[i, ] <- c(0.5, 0.5)  # asumsi netral
  }
}

# Vektor awal
S2 <- c(0.5, 0.5)

# Iterasi
for (iter in 1:max_iter) {
  S2_new <- as.numeric(S2 %*% P2)
  if (max(abs(S2_new - S2)) < tol) break
  S2 <- S2_new
}

# Output
cat("=== PANGSA PASAR NB170 ===\n")
## === PANGSA PASAR NB170 ===
cat(sprintf("  Perolehan konsumen (P) : %.4f  (%.2f%%)\n", S2[1], S2[1]*100))
##   Perolehan konsumen (P) : 0.4815  (48.15%)
cat(sprintf("  Kehilangan konsumen (K): %.4f  (%.2f%%)\n", S2[2], S2[2]*100))
##   Kehilangan konsumen (K): 0.5185  (51.85%)
# Tabel
df_ms <- data.frame(
  Kondisi      = c("Perolehan (P)","Kehilangan (K)"),
  Probabilitas = round(S2, 4),
  Persentase   = paste0(round(S2 * 100, 2), "%")
)

knitr::kable(
  df_ms,
  caption = "Tabel 10. Pangsa Pasar NB170 (Steady State 2×2)",
  align   = "c"
)
Tabel 10. Pangsa Pasar NB170 (Steady State 2×2)
Kondisi Probabilitas Persentase
Perolehan (P) 0.4815 48.15%
Kehilangan (K) 0.5185 51.85%

Prediksi Penjualan Juli 2017

Prediksi penjualan bulan Juli 2017 dilakukan berdasarkan nilai penjualan bulan sebelumnya (Juni 2017) serta proporsi kondisi Perolehan (P) dan Kehilangan (K) yang diperoleh dari hasil analisis.

Rumus yang digunakan adalah sebagai berikut:

\[ \text{Prediksi Juli} = \text{Jual Juni} + (\text{Jual Juni} \times \% \text{Perolehan}) - (\text{Jual Juni} \times \% \text{Kehilangan}) \]

dengan: - \(\text{Jual Juni}\) = jumlah penjualan pada bulan Juni 2017
- \(\% \text{Perolehan}\) = proporsi kejadian perolehan (P)
- \(\% \text{Kehilangan}\) = proporsi kejadian kehilangan (K)

Persentase perolehan dan kehilangan diperoleh dari hasil reduksi probabilitas atau pangsa pasar pada kondisi stabil.

Nilai prediksi ini mencerminkan estimasi perubahan penjualan dengan mempertimbangkan kecenderungan peningkatan dan penurunan yang terjadi pada periode sebelumnya.

Sebagai hasil akhir, jika nilai persentase perolehan lebih besar dibandingkan kehilangan, maka penjualan diprediksi mengalami peningkatan. Sebaliknya, jika persentase kehilangan lebih besar, maka penjualan diprediksi menurun.

jual_juni <- penjualan[length(penjualan)]   # Jun-17 = 12

pct_perolehan  <- S2[1]
pct_kehilangan <- S2[2]

# Model prediksi
prediksi_juli <- jual_juni + 
  (jual_juni * pct_perolehan) - 
  (jual_juni * pct_kehilangan)


cat(sprintf("  Penjualan Juni 2017     : %d pcs\n", jual_juni))
##   Penjualan Juni 2017     : 12 pcs
cat(sprintf("  %% Perolehan             : %.2f%%\n", pct_perolehan*100))
##   % Perolehan             : 48.15%
cat(sprintf("  %% Kehilangan            : %.2f%%\n", pct_kehilangan*100))
##   % Kehilangan            : 51.85%
cat(sprintf("  Prediksi Juli 2017      : %.2f pcs ≈ %d pcs\n",
            prediksi_juli, round(prediksi_juli)))
##   Prediksi Juli 2017      : 11.56 pcs ≈ 12 pcs
# Tabel ringkasan
df_pred <- data.frame(
  Keterangan = c(
    "Penjualan Juni 2017",
    "% Perolehan (P)",
    "% Kehilangan (K)",
    "Prediksi Juli 2017 (desimal)",
    "Prediksi Juli 2017 (dibulatkan)"
  ),
  Nilai = c(
    jual_juni,
    round(pct_perolehan * 100, 2),
    round(pct_kehilangan * 100, 2),
    round(prediksi_juli, 4),
    round(prediksi_juli)
  )
)

knitr::kable(
  df_pred,
  caption = "Tabel 11. Ringkasan Prediksi Penjualan NB170",
  align   = "c"
)
Tabel 11. Ringkasan Prediksi Penjualan NB170
Keterangan Nilai
Penjualan Juni 2017 12.0000
% Perolehan (P) 48.1500
% Kehilangan (K) 51.8500
Prediksi Juli 2017 (desimal) 11.5556
Prediksi Juli 2017 (dibulatkan) 12.0000

Visualisasi

# PLOT DATA HISTORIS + PREDIKSI

par(mfrow = c(1, 2), mar = c(5, 4, 4, 2))

# Plot 1: Data penjualan + prediksi
plot(1:n, penjualan, type = "b", pch = 16, col = "steelblue",
     xlab = "Bulan ke-", ylab = "Penjualan (pcs)",
     main = "Penjualan NB170 Jan 2015 – Jun 2017",
     xaxt = "n", lwd = 2)

axis(1, at = c(1, 7, 13, 19, 25, 30),
     labels = c("Jan-15","Jul-15","Jan-16","Jul-16","Jan-17","Jun-17"),
     cex.axis = 0.7)

# Titik prediksi Juli 2017
points(n + 1, round(prediksi_juli), pch = 17, col = "red", cex = 1.5)

# Garis ke prediksi
lines(c(n, n + 1), c(jual_juni, round(prediksi_juli)),
      lty = 2, col = "red", lwd = 2)

# Legend
legend("topright",
       legend = c("Historis", "Prediksi Jul-17"),
       col = c("steelblue","red"),
       pch = c(16, 17), lty = c(1, 2), cex = 0.8)

# Garis rata-rata
abline(h = mean(penjualan), lty = 3, col = "gray50")
text(2, mean(penjualan) + 0.5,
     paste0("rata-rata = ", round(mean(penjualan), 1)),
     col = "gray40", cex = 0.75)


# Plot 2: Pangsa Pasar
barplot(S2 * 100,
        names.arg = c("Perolehan (P)", "Kehilangan (K)"),
        col = c("steelblue", "tomato"),
        ylab = "Probabilitas (%)",
        main = "Pangsa Pasar NB170\n(Steady State 2×2)",
        ylim = c(0, 100))

text(0.7, S2[1] * 100 + 3,
     paste0(round(S2[1]*100, 2), "%"), cex = 0.9)

text(1.9, S2[2] * 100 + 3,
     paste0(round(S2[2]*100, 2), "%"), cex = 0.9)

## Ringkasan

cat("  RINGKASAN ANALISIS RANTAI MARKOV ORDE DUA\n")
##   RINGKASAN ANALISIS RANTAI MARKOV ORDE DUA
cat("  Produk: DOVE SHP NOURISHING BLACK 170 ML (NB170)\n")
##   Produk: DOVE SHP NOURISHING BLACK 170 ML (NB170)
cat("\n1. STEADY STATE ORDE DUA (4 state):\n")
## 
## 1. STEADY STATE ORDE DUA (4 state):
cat(sprintf("   PP: %.4f | PK: %.4f | KP: %.4f | KK: %.4f\n",
            S[1], S[2], S[3], S[4]))
##    PP: 0.1111 | PK: 0.3704 | KP: 0.3704 | KK: 0.1481
cat("\n2. PANGSA PASAR (Steady State 2×2):\n")
## 
## 2. PANGSA PASAR (Steady State 2×2):
cat(sprintf("   Perolehan konsumen : %.4f (%.2f%%)\n", S2[1], S2[1]*100))
##    Perolehan konsumen : 0.4815 (48.15%)
cat(sprintf("   Kehilangan konsumen: %.4f (%.2f%%)\n", S2[2], S2[2]*100))
##    Kehilangan konsumen: 0.5185 (51.85%)
# Tren pasar
trend <- ifelse(S2[1] > S2[2], "MENINGKAT ▲", "MENURUN ▼")
cat(sprintf("\n3. TREN PASAR      : %s\n", trend))
## 
## 3. TREN PASAR      : MENURUN ▼
# Prediksi
cat(sprintf("   Penjualan Juni 2017 : %d pcs\n", jual_juni))
##    Penjualan Juni 2017 : 12 pcs
cat(sprintf("   Prediksi Juli 2017  : %d pcs\n", round(prediksi_juli)))
##    Prediksi Juli 2017  : 12 pcs
cat(sprintf("   Perubahan prediksi  : %.2f pcs (%s)\n",
            abs(prediksi_juli - jual_juni),
            ifelse(prediksi_juli >= jual_juni, "naik", "turun")))
##    Perubahan prediksi  : 0.44 pcs (turun)

DATA PENJUALAN NOC320 (Z9)

Data penjualan bulanan DOVE SHP NOURISHING OIL CARE 320 ML dari Januari 2015 hingga Juni 2017 di Swalayan Pamella 1, Yogyakarta. Catatan: nilai Oktober 2015 (Oct-15) = 0.

# DATA PENJUALAN Z9 (NOC320) Jan 2015 - Jun 2017
periode <- c(
  "Jan-15","Feb-15","Mar-15","Apr-15","May-15","Jun-15",
  "Jul-15","Aug-15","Sep-15","Oct-15","Nov-15","Dec-15",
  "Jan-16","Feb-16","Mar-16","Apr-16","May-16","Jun-16",
  "Jul-16","Aug-16","Sep-16","Oct-16","Nov-16","Dec-16",
  "Jan-17","Feb-17","Mar-17","Apr-17","May-17","Jun-17"
)

penjualan <- c(
  10, 11, 2,  5,  8,  1,   # 2015 Jan-Jun
   7,  4, 2,  0,  1, 10,   # 2015 Jul-Dec  
  16, 17, 15,  1,  9, 15,  # 2016 Jan-Jun
  17,  8, 16, 19, 19, 26,  # 2016 Jul-Dec
  12,  7, 19, 16, 15,  8   # 2017 Jan-Jun
)

df <- data.frame(Periode = periode, Penjualan = penjualan)
knitr::kable(df, caption = "Tabel 1. Data Penjualan NOC320 (Z9)", align = "c")
Tabel 1. Data Penjualan NOC320 (Z9)
Periode Penjualan
Jan-15 10
Feb-15 11
Mar-15 2
Apr-15 5
May-15 8
Jun-15 1
Jul-15 7
Aug-15 4
Sep-15 2
Oct-15 0
Nov-15 1
Dec-15 10
Jan-16 16
Feb-16 17
Mar-16 15
Apr-16 1
May-16 9
Jun-16 15
Jul-16 17
Aug-16 8
Sep-16 16
Oct-16 19
Nov-16 19
Dec-16 26
Jan-17 12
Feb-17 7
Mar-17 19
Apr-17 16
May-17 15
Jun-17 8

Penentuan State (Perolehan / Kehilangan)

State \(X_t\) ditentukan berdasarkan perubahan penjualan bulan ke-\(t\) dibanding bulan ke-\((t-1)\):

\[X_t = \begin{cases} 0 \text{ (P = Perolehan)} & \text{jika penjualan naik atau sama} \\ 1 \text{ (K = Kehilangan)} & \text{jika penjualan turun} \end{cases}\]

# TENTUKAN STATE: P = 0 (naik/sama), K = 1 (turun)
n <- length(penjualan)

# State: bandingkan bulan t dengan bulan t-1
# Indeks 2..n  →  29 nilai state
state_label <- ifelse(penjualan[2:n] >= penjualan[1:(n-1)], "P", "K")
state_val   <- ifelse(penjualan[2:n] >= penjualan[1:(n-1)],  0,   1)

df_state <- data.frame(
  Periode    = periode[2:n],
  Penjualan  = penjualan[2:n],
  Prev       = penjualan[1:(n-1)],
  Perubahan  = penjualan[2:n] - penjualan[1:(n-1)],
  State_Label= state_label,
  State_Val  = state_val
)

knitr::kable(df_state,
  col.names = c("Periode","Jual (t)","Jual (t-1)","Δ","State","Nilai"),
  caption   = "Tabel 2. Penentuan State Perbulan",
  align     = "c")
Tabel 2. Penentuan State Perbulan
Periode Jual (t) Jual (t-1) Δ State Nilai
Feb-15 11 10 1 P 0
Mar-15 2 11 -9 K 1
Apr-15 5 2 3 P 0
May-15 8 5 3 P 0
Jun-15 1 8 -7 K 1
Jul-15 7 1 6 P 0
Aug-15 4 7 -3 K 1
Sep-15 2 4 -2 K 1
Oct-15 0 2 -2 K 1
Nov-15 1 0 1 P 0
Dec-15 10 1 9 P 0
Jan-16 16 10 6 P 0
Feb-16 17 16 1 P 0
Mar-16 15 17 -2 K 1
Apr-16 1 15 -14 K 1
May-16 9 1 8 P 0
Jun-16 15 9 6 P 0
Jul-16 17 15 2 P 0
Aug-16 8 17 -9 K 1
Sep-16 16 8 8 P 0
Oct-16 19 16 3 P 0
Nov-16 19 19 0 P 0
Dec-16 26 19 7 P 0
Jan-17 12 26 -14 K 1
Feb-17 7 12 -5 K 1
Mar-17 19 7 12 P 0
Apr-17 16 19 -3 K 1
May-17 15 16 -1 K 1
Jun-17 8 15 -7 K 1

Rantai Markov Orde Dua

Definisi State Gabungan \(Y_t\)

Untuk orde kedua, state gabungan \(Y_t\) didefinisikan berdasarkan dua bulan berurutan \((X_t, X_{t-1})\):

\(Y_t\) \(X_t\) \(X_{t-1}\) Kode
0 0 (P) 0 (P) PP
1 0 (P) 1 (K) PK
2 1 (K) 0 (P) KP
3 1 (K) 1 (K) KK
# STATE GABUNGAN Y_t  (indeks 2..28 dari state_val → 28 pasang)
# state_val punya 29 elemen (indeks 1..29 di R)
# Y_t dibentuk dari pasangan (state_val[t], state_val[t-1])
sv <- state_val   


Xt   <- sv[2:length(sv)]       
Xt_1 <- sv[1:(length(sv)-1)]   

# Kode Y
Y_val <- ifelse(Xt == 0 & Xt_1 == 0, 0,
         ifelse(Xt == 0 & Xt_1 == 1, 1,
         ifelse(Xt == 1 & Xt_1 == 0, 2, 3)))

Y_label <- c("PP","PK","KP","KK")[Y_val + 1]

df_Y <- data.frame(
  t         = 2:(length(sv)),
  Periode   = periode[3:n],          
  Xt_1_val  = Xt_1,
  Xt_val    = Xt,
  Y_val     = Y_val,
  Y_label   = Y_label
)

knitr::kable(df_Y,
  col.names = c("t","Periode","X(t-1)","X(t)","Y_t","Label"),
  caption   = "Tabel 3. State Gabungan Y_t (Orde Dua)",
  align     = "c")
Tabel 3. State Gabungan Y_t (Orde Dua)
t Periode X(t-1) X(t) Y_t Label
2 Mar-15 0 1 2 KP
3 Apr-15 1 0 1 PK
4 May-15 0 0 0 PP
5 Jun-15 0 1 2 KP
6 Jul-15 1 0 1 PK
7 Aug-15 0 1 2 KP
8 Sep-15 1 1 3 KK
9 Oct-15 1 1 3 KK
10 Nov-15 1 0 1 PK
11 Dec-15 0 0 0 PP
12 Jan-16 0 0 0 PP
13 Feb-16 0 0 0 PP
14 Mar-16 0 1 2 KP
15 Apr-16 1 1 3 KK
16 May-16 1 0 1 PK
17 Jun-16 0 0 0 PP
18 Jul-16 0 0 0 PP
19 Aug-16 0 1 2 KP
20 Sep-16 1 0 1 PK
21 Oct-16 0 0 0 PP
22 Nov-16 0 0 0 PP
23 Dec-16 0 0 0 PP
24 Jan-17 0 1 2 KP
25 Feb-17 1 1 3 KK
26 Mar-17 1 0 1 PK
27 Apr-17 0 1 2 KP
28 May-17 1 1 3 KK
29 Jun-17 1 1 3 KK

Matriks Frekuensi Transisi Orde Dua

Hitung frekuensi transisi \(f_{ij}\) dari state \(Y_t\) ke \(Y_{t+1}\)

# HITUNG FREKUENSI TRANSISI f_ij  (4x4)
# dari Y_t ke Y_{t+1}
states <- 0:3

frek <- matrix(0, nrow = 4, ncol = 4,
               dimnames = list(
                 paste0("dari_", c("PP","PK","KP","KK")),
                 paste0("ke_",   c("PP","PK","KP","KK"))
               ))

for (t in 1:(length(Y_val) - 1)) {
  i <- Y_val[t]   + 1   # baris  (1-based)
  j <- Y_val[t+1] + 1   # kolom  (1-based)
  frek[i, j] <- frek[i, j] + 1
}

knitr::kable(frek,
  caption = "Tabel 4. Matriks Frekuensi Transisi f_ij (4×4)",
  align   = "c")
Tabel 4. Matriks Frekuensi Transisi f_ij (4×4)
ke_PP ke_PK ke_KP ke_KK
dari_PP 5 0 4 0
dari_PK 4 0 2 0
dari_KP 0 3 0 4
dari_KK 0 3 0 2

Matriks Probabilitas Transisi Orde Dua

\[P_{ij} = \frac{f_{ij}}{\sum_{j=0}^{3} f_{ij}}\]

# HITUNG MATRIKS PROBABILITAS TRANSISI  P (4x4)
row_sum <- rowSums(frek)

prob <- matrix(0, nrow = 4, ncol = 4,
               dimnames = list(
                 c("PP","PK","KP","KK"),
                 c("PP","PK","KP","KK")
               ))

for (i in 1:4) {
  if (row_sum[i] > 0) {
    prob[i, ] <- frek[i, ] / row_sum[i]
  }
}

knitr::kable(round(prob, 4),
  caption = "Tabel 5. Matriks Probabilitas Transisi P (4×4)",
  align   = "c")
Tabel 5. Matriks Probabilitas Transisi P (4×4)
PP PK KP KK
PP 0.5556 0.0000 0.4444 0.0000
PK 0.6667 0.0000 0.3333 0.0000
KP 0.0000 0.4286 0.0000 0.5714
KK 0.0000 0.6000 0.0000 0.4000

Probabilitas Steady State

Iterasi \(S(t) = S(0) \cdot P\)

Mulai dari vektor probabilitas awal seragam: \[S(0) = [0.25 \quad 0.25 \quad 0.25 \quad 0.25]\]

# HITUNG STEADY STATE  S(t) = S(0) · P  (iteratif)
S <- c(0.25, 0.25, 0.25, 0.25)

tol       <- 1e-8
max_iter  <- 10000
history   <- list()

for (iter in 1:max_iter) {
  S_new <- S %*% prob   # baris × matriks
  S_new <- as.numeric(S_new)
  
  # Simpan setiap 500 iterasi + awal
  if (iter <= 5 || iter %% 500 == 0) {
    history[[length(history) + 1]] <- c(iter = iter, round(S_new, 6))
  }
  
  if (max(abs(S_new - S)) < tol) {
    cat("Steady state tercapai pada iterasi ke:", iter, "\n")
    S <- S_new
    break
  }
  S <- S_new
}
## Steady state tercapai pada iterasi ke: 18
# Tampilkan riwayat iterasi
df_hist <- do.call(rbind, history)
df_hist <- as.data.frame(df_hist)
colnames(df_hist) <- c("Iterasi", "S_PP", "S_PK", "S_KP", "S_KK")
knitr::kable(df_hist,
  caption = "Tabel 6. Riwayat Iterasi Menuju Steady State",
  align   = "c", row.names = FALSE)
Tabel 6. Riwayat Iterasi Menuju Steady State
Iterasi S_PP S_PK S_KP S_KK
1 0.305556 0.257143 0.194444 0.242857
2 0.341182 0.229048 0.221517 0.208254
3 0.342244 0.219888 0.227985 0.209883
4 0.336728 0.223638 0.225404 0.214230
5 0.336163 0.225140 0.224203 0.214495
cat("\nHASIL STEADY STATE \n")
## 
## HASIL STEADY STATE
cat(sprintf("  P_0 (PP) = %.4f\n", S[1]))
##   P_0 (PP) = 0.3369
cat(sprintf("  P_1 (PK) = %.4f\n", S[2]))
##   P_1 (PK) = 0.2246
cat(sprintf("  P_2 (KP) = %.4f\n", S[3]))
##   P_2 (KP) = 0.2246
cat(sprintf("  P_3 (KK) = %.4f\n", S[4]))
##   P_3 (KK) = 0.2139
cat(sprintf("  Jumlah   = %.4f\n", sum(S)))
##   Jumlah   = 1.0000
df_ss <- data.frame(
  State       = c("0-PP","1-PK","2-KP","3-KK"),
  Probabilitas = round(S, 4)
)
knitr::kable(df_ss,
  caption = "Tabel 7. Probabilitas Steady State NOC320",
  align   = "c")
Tabel 7. Probabilitas Steady State NOC320
State Probabilitas
0-PP 0.3369
1-PK 0.2246
2-KP 0.2246
3-KK 0.2139

Pangsa Pasar (Market Share)

Jumlah Kejadian di Kondisi Stabil

Dari vektor steady state \(S^{(n)} = [P_0^n, P_1^n, P_2^n, P_3^n]\), jumlah kejadian perpindahan di kondisi stabil dihitung sebagai:

\[f_{ij}^{stabil} = S_i^{(n)} \times (\text{total frekuensi})\]

# JUMLAH KEJADIAN STABIL (dibulatkan)
total_trans <- sum(frek)  # total transisi

f_stabil <- round(S * total_trans)
names(f_stabil) <- c("PP","PK","KP","KK")

cat("Total transisi yang diamati:", total_trans, "\n\n")
## Total transisi yang diamati: 27
df_fstab <- data.frame(
  State = c("PP (f00)","PK (f01)","KP (f10)","KK (f11)"),
  Frekuensi_Stabil = f_stabil
)
knitr::kable(df_fstab,
  caption = "Tabel 8. Frekuensi di Kondisi Stabil (Orde Dua ke Orde Satu)",
  align   = "c", row.names = FALSE)
Tabel 8. Frekuensi di Kondisi Stabil (Orde Dua ke Orde Satu)
State Frekuensi_Stabil
PP (f00) 9
PK (f01) 6
KP (f10) 6
KK (f11) 6

Matriks Probabilitas Transisi Baru (2×2)

Setelah direduksi kembali ke perspektif Perolehan (P) vs Kehilangan (K):

\[P_{new} = \begin{bmatrix} \frac{f_{PP}}{f_{PP}+f_{PK}} & \frac{f_{PK}}{f_{PP}+f_{PK}} \\[6pt] \frac{f_{KP}}{f_{KP}+f_{KK}} & \frac{f_{KK}}{f_{KP}+f_{KK}} \end{bmatrix}\]

# MATRIKS PROBABILITAS TRANSISI BARU (2x2)
f00 <- f_stabil["PP"];  f01 <- f_stabil["PK"]
f10 <- f_stabil["KP"];  f11 <- f_stabil["KK"]

P00_new <- f00 / (f00 + f01)
P01_new <- f01 / (f00 + f01)
P10_new <- f10 / (f10 + f11)
P11_new <- f11 / (f10 + f11)

mat_baru <- matrix(
  c(P00_new, P01_new, P10_new, P11_new),
  nrow = 2, byrow = TRUE,
  dimnames = list(c("P (Perolehan)","K (Kehilangan)"),
                  c("→ P","→ K"))
)

knitr::kable(round(mat_baru, 4),
  caption = "Tabel 9. Matriks Probabilitas Transisi Baru (2×2)",
  align   = "c")
Tabel 9. Matriks Probabilitas Transisi Baru (2×2)
→ P → K
P (Perolehan) 0.6 0.4
K (Kehilangan) 0.5 0.5

Steady State 2×2 (Pangsa Pasar)

# STEADY STATE 2x2  → Pangsa Pasar
S2 <- c(0.5, 0.5)   # vektor awal

for (iter in 1:max_iter) {
  S2_new <- as.numeric(S2 %*% mat_baru)
  if (max(abs(S2_new - S2)) < tol) break
  S2 <- S2_new
}

cat("=== PANGSA PASAR NOC320 ===\n")
## === PANGSA PASAR NOC320 ===
cat(sprintf("  Perolehan konsumen (P) : %.4f  (%.2f%%)\n", S2[1], S2[1]*100))
##   Perolehan konsumen (P) : 0.5556  (55.56%)
cat(sprintf("  Kehilangan konsumen (K): %.4f  (%.2f%%)\n", S2[2], S2[2]*100))
##   Kehilangan konsumen (K): 0.4444  (44.44%)
df_ms <- data.frame(
  Kondisi      = c("Perolehan (P)","Kehilangan (K)"),
  Probabilitas = round(S2, 4),
  Persentase   = paste0(round(S2 * 100, 2), "%")
)
knitr::kable(df_ms,
  caption = "Tabel 10. Pangsa Pasar NOC320 (Steady State 2×2)",
  align   = "c")
Tabel 10. Pangsa Pasar NOC320 (Steady State 2×2)
Kondisi Probabilitas Persentase
Perolehan (P) 0.5556 55.56%
Kehilangan (K) 0.4444 44.44%

Prediksi Penjualan Juli 2017

Menggunakan rumus prediksi:

\[\text{Prediksi}_{\text{Juli}} = \text{Jual}_{\text{Juni}} + (\text{Jual}_{\text{Juni}} \times \%\text{Perolehan}) - (\text{Jual}_{\text{Juni}} \times \%\text{Kehilangan})\]

# PREDIKSI PENJUALAN JULI 2017
jual_juni <- penjualan[length(penjualan)]   # Jun-17

pct_perolehan  <- S2[1]
pct_kehilangan <- S2[2]

prediksi_juli <- jual_juni + (jual_juni * pct_perolehan) - (jual_juni * pct_kehilangan)

cat("=== PREDIKSI PENJUALAN ===\n")
## === PREDIKSI PENJUALAN ===
cat(sprintf("  Penjualan Juni 2017     : %d pcs\n", jual_juni))
##   Penjualan Juni 2017     : 8 pcs
cat(sprintf("  %% Perolehan             : %.2f%%\n", pct_perolehan*100))
##   % Perolehan             : 55.56%
cat(sprintf("  %% Kehilangan            : %.2f%%\n", pct_kehilangan*100))
##   % Kehilangan            : 44.44%
cat(sprintf("  Prediksi Juli 2017      : %.2f pcs ≈ %d pcs\n",
            prediksi_juli, round(prediksi_juli)))
##   Prediksi Juli 2017      : 8.89 pcs ≈ 9 pcs
df_pred <- data.frame(
  Keterangan = c(
    "Penjualan Juni 2017",
    "% Perolehan (P)",
    "% Kehilangan (K)",
    "Prediksi Juli 2017 (desimal)",
    "Prediksi Juli 2017 (dibulatkan)"
  ),
  Nilai = c(
    jual_juni,
    round(pct_perolehan * 100, 2),
    round(pct_kehilangan * 100, 2),
    round(prediksi_juli, 4),
    round(prediksi_juli)
  )
)

knitr::kable(df_pred,
  caption = "Tabel 11. Ringkasan Prediksi Penjualan NOC320",
  align   = "c")
Tabel 11. Ringkasan Prediksi Penjualan NOC320
Keterangan Nilai
Penjualan Juni 2017 8.0000
% Perolehan (P) 55.5600
% Kehilangan (K) 44.4400
Prediksi Juli 2017 (desimal) 8.8889
Prediksi Juli 2017 (dibulatkan) 9.0000

Visualisasi

# PLOT DATA HISTORIS + PREDIKSI
par(mfrow = c(1, 2), mar = c(5, 4, 4, 2))

# --- Plot 1: Data penjualan + prediksi ---
plot(1:n, penjualan, type = "b", pch = 16, col = "steelblue",
     xlab = "Bulan ke-", ylab = "Penjualan (pcs)",
     main = "Penjualan NOC320 (Z9) Jan 2015 – Jun 2017",
     xaxt = "n", lwd = 2)
axis(1, at = c(1, 7, 13, 19, 25, 30),
     labels = c("Jan-15","Jul-15","Jan-16","Jul-16","Jan-17","Jun-17"), cex.axis = 0.7)
points(n + 1, round(prediksi_juli), pch = 17, col = "red", cex = 1.5)
lines(c(n, n + 1), c(jual_juni, round(prediksi_juli)),
      lty = 2, col = "red", lwd = 2)
legend("topright",
       legend = c("Historis", "Prediksi Jul-17"),
       col = c("steelblue","red"), pch = c(16, 17), lty = c(1, 2), cex = 0.8)
abline(h = mean(penjualan), lty = 3, col = "gray50")
text(2, mean(penjualan) + 0.5, paste0("rata-rata = ", round(mean(penjualan), 1)),
     col = "gray40", cex = 0.75)

# --- Plot 2: Pangsa Pasar ---
barplot(S2 * 100,
        names.arg = c("Perolehan (P)", "Kehilangan (K)"),
        col = c("steelblue", "tomato"),
        ylab = "Probabilitas (%)",
        main = "Pangsa Pasar NOC320\n(Steady State Orde 2)",
        ylim = c(0, 100))
text(0.7, S2[1] * 100 + 3, paste0(round(S2[1]*100, 2), "%"), cex = 0.9)
text(1.9, S2[2] * 100 + 3, paste0(round(S2[2]*100, 2), "%"), cex = 0.9)


Ringkasan Hasil

cat("  RINGKASAN ANALISIS RANTAI MARKOV ORDE DUA\n")
##   RINGKASAN ANALISIS RANTAI MARKOV ORDE DUA
cat("  Produk: DOVE SHP NOURISHING OIL CARE 320 ML (Z9)\n")
##   Produk: DOVE SHP NOURISHING OIL CARE 320 ML (Z9)
cat("1. STEADY STATE ORDE DUA (4 state):\n")
## 1. STEADY STATE ORDE DUA (4 state):
cat(sprintf("   PP: %.4f | PK: %.4f | KP: %.4f | KK: %.4f\n",
            S[1], S[2], S[3], S[4]))
##    PP: 0.3369 | PK: 0.2246 | KP: 0.2246 | KK: 0.2139
cat("\n2. PANGSA PASAR (Steady State 2×2):\n")
## 
## 2. PANGSA PASAR (Steady State 2×2):
cat(sprintf("   Perolehan konsumen : %.4f (%.2f%%)\n", S2[1], S2[1]*100))
##    Perolehan konsumen : 0.5556 (55.56%)
cat(sprintf("   Kehilangan konsumen: %.4f (%.2f%%)\n", S2[2], S2[2]*100))
##    Kehilangan konsumen: 0.4444 (44.44%)
trend <- ifelse(S2[1] > S2[2], "MENINGKAT ▲", "MENURUN ▼")
cat(sprintf("\n3. TREN PASAR      : %s\n", trend))
## 
## 3. TREN PASAR      : MENINGKAT ▲
cat(sprintf("   Penjualan Juni 2017 : %d pcs\n", jual_juni))
##    Penjualan Juni 2017 : 8 pcs
cat(sprintf("   Prediksi Juli 2017  : %d pcs\n", round(prediksi_juli)))
##    Prediksi Juli 2017  : 9 pcs
cat(sprintf("   Perubahan prediksi  : %.2f pcs (%s)\n",
            abs(prediksi_juli - jual_juni),
            ifelse(prediksi_juli >= jual_juni, "naik", "turun")))
##    Perubahan prediksi  : 0.89 pcs (naik)