---
title: "Factor Scores & Korelasi"
---
```{r}
#| label: setup
#| echo: false
source("_common.R")
```
Bagian ini memuat ekstraksi *factor scores*, statistik deskriptif, matriks korelasi, serta visualisasi distribusi dan density factor scores.
## Ekstraksi Factor Scores
```{r}
#| label: extract-fscores
Fscores_peb <- lavPredict(fit_peb, type = "lv")
Fscores_ol <- lavPredict(fit_ol, type = "lv")
Fscores_ccs <- lavPredict(fit_ccs, type = "lv")
data_Fscores <- data.frame(
PEB = Fscores_peb[, "PEB"],
OL = Fscores_ol[, "OL"],
CCS = Fscores_ccs[, "GCCS"]
)
cat("Factor scores berhasil diekstraksi:", nrow(data_Fscores), "observasi x 3 variabel")
```
## Statistik Deskriptif Factor Scores
```{r}
var_desc <- psych::describe(data_Fscores, type = 2)
knitr::kable(data.frame(
Variabel = rownames(var_desc), N = var_desc$n,
Mean = round(var_desc$mean, 3), SD = round(var_desc$sd, 3),
Min = round(var_desc$min, 3), Max = round(var_desc$max, 3),
Skewness = round(var_desc$skew, 3), Kurtosis = round(var_desc$kurtosis, 3),
check.names = FALSE
), caption = "Statistik Deskriptif Factor Scores", row.names = FALSE)
```
## Distribusi Factor Scores — Histogram & Density
```{r}
#| label: distribution-scores
#| fig-width: 12
#| fig-height: 8
#| code-fold: true
#| code-summary: "Kode distribusi histogram + density"
# ---- Hitung cutoff per variabel ----
peb_low <- mean(data_Fscores$PEB, na.rm = TRUE) - 0.5 * sd(data_Fscores$PEB, na.rm = TRUE)
peb_hi <- mean(data_Fscores$PEB, na.rm = TRUE) + 0.5 * sd(data_Fscores$PEB, na.rm = TRUE)
ccs_low <- mean(data_Fscores$CCS, na.rm = TRUE) - 0.5 * sd(data_Fscores$CCS, na.rm = TRUE)
ccs_hi <- mean(data_Fscores$CCS, na.rm = TRUE) + 0.5 * sd(data_Fscores$CCS, na.rm = TRUE)
ol_low <- mean(data_Fscores$OL, na.rm = TRUE) - 0.5 * sd(data_Fscores$OL, na.rm = TRUE)
ol_hi <- mean(data_Fscores$OL, na.rm = TRUE) + 0.5 * sd(data_Fscores$OL, na.rm = TRUE)
# Kategorisasi untuk warna histogram
breaks_peb <- hist(data_Fscores$PEB, plot = FALSE, breaks = 20)
colors_peb <- cut(breaks_peb$mids, breaks = c(-Inf, peb_low, peb_hi, Inf), labels = c("lightsteelblue", "steelblue", "darkslategray"))
breaks_ccs <- hist(data_Fscores$CCS, plot = FALSE, breaks = 20)
colors_ccs <- cut(breaks_ccs$mids, breaks = c(-Inf, ccs_low, ccs_hi, Inf), labels = c("lightsalmon", "coral", "darkred"))
breaks_ol <- hist(data_Fscores$OL, plot = FALSE, breaks = 20)
colors_ol <- cut(breaks_ol$mids, breaks = c(-Inf, ol_low, ol_hi, Inf), labels = c("palegreen", "lightgreen", "darkgreen"))
# Jumlah per kategori
categorize_score <- function(scores, labels = c("Rendah", "Sedang", "Tinggi")) {
m <- mean(scores, na.rm = TRUE); s <- sd(scores, na.rm = TRUE)
ifelse(scores < m - 0.5*s, labels[1], ifelse(scores > m + 0.5*s, labels[3], labels[2]))
}
data_Fscores$PEB_cat <- categorize_score(data_Fscores$PEB)
data_Fscores$CCS_cat <- categorize_score(data_Fscores$CCS)
data_Fscores$OL_cat <- categorize_score(data_Fscores$OL)
peb_n <- table(data_Fscores$PEB_cat)
ccs_n <- table(data_Fscores$CCS_cat)
ol_n <- table(data_Fscores$OL_cat)
par(mfrow = c(2, 3), mar = c(7, 4, 4, 2) + 0.5)
# --- Histogram 1: PEB ---
hist(data_Fscores$PEB, main = "Distribusi PEB", xlab = "Skor", col = as.character(colors_peb), border = "white", xlim = c(-4, 3), ylim = c(0, 150), breaks = 20)
op <- par(family = "mono")
legend("bottom", inset = c(0, -0.42),
legend = c(
sprintf("%-6s (n=%3d) [%6.2f, %5.2f]", "Rendah", peb_n["Rendah"], min(data_Fscores$PEB, na.rm = TRUE), peb_low),
sprintf("%-6s (n=%3d) [%6.2f, %5.2f]", "Sedang", peb_n["Sedang"], peb_low, peb_hi),
sprintf("%-6s (n=%3d) [%6.2f, %5.2f]", "Tinggi", peb_n["Tinggi"], peb_hi, max(data_Fscores$PEB, na.rm = TRUE))
), fill = c("lightsteelblue", "steelblue", "darkslategray"), cex = 0.85, bty = "n", xpd = TRUE)
par(op)
# --- Histogram 2: CCS ---
hist(data_Fscores$CCS, main = "Distribusi CCS", xlab = "Skor", col = as.character(colors_ccs), border = "white", xlim = c(-4, 3), ylim = c(0, 150), breaks = 20)
op <- par(family = "mono")
legend("bottom", inset = c(0, -0.42),
legend = c(
sprintf("%-6s (n=%3d) [%6.2f, %5.2f]", "Rendah", ccs_n["Rendah"], min(data_Fscores$CCS, na.rm = TRUE), ccs_low),
sprintf("%-6s (n=%3d) [%6.2f, %5.2f]", "Sedang", ccs_n["Sedang"], ccs_low, ccs_hi),
sprintf("%-6s (n=%3d) [%6.2f, %5.2f]", "Tinggi", ccs_n["Tinggi"], ccs_hi, max(data_Fscores$CCS, na.rm = TRUE))
), fill = c("lightsalmon", "coral", "darkred"), cex = 0.85, bty = "n", xpd = TRUE)
par(op)
# --- Histogram 3: OL ---
hist(data_Fscores$OL, main = "Distribusi OL", xlab = "Skor", col = as.character(colors_ol), border = "white", xlim = c(-4, 3), ylim = c(0, 150), breaks = 20)
op <- par(family = "mono")
legend("bottom", inset = c(0, -0.42),
legend = c(
sprintf("%-6s (n=%3d) [%6.2f, %5.2f]", "Rendah", ol_n["Rendah"], min(data_Fscores$OL, na.rm = TRUE), ol_low),
sprintf("%-6s (n=%3d) [%6.2f, %5.2f]", "Sedang", ol_n["Sedang"], ol_low, ol_hi),
sprintf("%-6s (n=%3d) [%6.2f, %5.2f]", "Tinggi", ol_n["Tinggi"], ol_hi, max(data_Fscores$OL, na.rm = TRUE))
), fill = c("palegreen", "lightgreen", "darkgreen"), cex = 0.85, bty = "n", xpd = TRUE)
par(op)
# --- Density Plot 1: PEB ---
plot(density(data_Fscores$PEB, na.rm = TRUE), main = "Density PEB", xlab = "Skor", xlim = c(-4, 3), ylim = c(0, 1.2), lwd = 2, col = "steelblue")
abline(v = peb_low, col = "steelblue", lty = 2, lwd = 1.2)
abline(v = peb_hi, col = "darkslategray", lty = 2, lwd = 1.2)
op <- par(family = "mono")
legend("bottom", inset = c(0, -0.38),
legend = c(
sprintf("Rendah (n=%3d): x < %5.2f", peb_n["Rendah"], peb_low),
sprintf("Sedang (n=%3d): %5.2f s.d. %5.2f", peb_n["Sedang"], peb_low, peb_hi),
sprintf("Tinggi (n=%3d): x > %5.2f", peb_n["Tinggi"], peb_hi)
), fill = c("lightsteelblue", "steelblue", "darkslategray"), cex = 0.85, bty = "n", xpd = TRUE)
par(op)
# --- Density Plot 2: CCS ---
plot(density(data_Fscores$CCS, na.rm = TRUE), main = "Density CCS", xlab = "Skor", xlim = c(-4, 3), ylim = c(0, 1.2), lwd = 2, col = "coral")
abline(v = ccs_low, col = "coral", lty = 2, lwd = 1.2)
abline(v = ccs_hi, col = "darkred", lty = 2, lwd = 1.2)
op <- par(family = "mono")
legend("bottom", inset = c(0, -0.38),
legend = c(
sprintf("Rendah (n=%3d): x < %5.2f", ccs_n["Rendah"], ccs_low),
sprintf("Sedang (n=%3d): %5.2f s.d. %5.2f", ccs_n["Sedang"], ccs_low, ccs_hi),
sprintf("Tinggi (n=%3d): x > %5.2f", ccs_n["Tinggi"], ccs_hi)
), fill = c("lightsalmon", "coral", "darkred"), cex = 0.85, bty = "n", xpd = TRUE)
par(op)
# --- Density Plot 3: OL ---
plot(density(data_Fscores$OL, na.rm = TRUE), main = "Density OL", xlab = "Skor", xlim = c(-4, 3), ylim = c(0, 1.2), lwd = 2, col = "lightgreen")
abline(v = ol_low, col = "lightgreen", lty = 2, lwd = 1.2)
abline(v = ol_hi, col = "darkgreen", lty = 2, lwd = 1.2)
op <- par(family = "mono")
legend("bottom", inset = c(0, -0.38),
legend = c(
sprintf("Rendah (n=%3d): x < %5.2f", ol_n["Rendah"], ol_low),
sprintf("Sedang (n=%3d): %5.2f s.d. %5.2f", ol_n["Sedang"], ol_low, ol_hi),
sprintf("Tinggi (n=%3d): x > %5.2f", ol_n["Tinggi"], ol_hi)
), fill = c("palegreen", "lightgreen", "darkgreen"), cex = 0.85, bty = "n", xpd = TRUE)
par(op)
par(mfrow = c(1, 1), mar = c(5, 4, 4, 2) + 0.1)
```
### Frekuensi Kategori
```{r}
for (v in c("PEB", "CCS", "OL")) {
scores <- data_Fscores[[v]]
cats <- categorize_score(scores)
freq <- table(cats)
pct <- round(prop.table(freq) * 100, 1)
cat(sprintf("\n%s: Rendah=%d (%.1f%%), Sedang=%d (%.1f%%), Tinggi=%d (%.1f%%)\n",
v, freq["Rendah"], pct["Rendah"], freq["Sedang"], pct["Sedang"], freq["Tinggi"], pct["Tinggi"]))
}
```
---
## Matriks Korelasi Pearson
```{r}
cor_matrix <- cor(data_Fscores[, c("PEB", "OL", "CCS")], use = "complete.obs")
corr_pvalues <- corr.test(data_Fscores[, c("PEB", "OL", "CCS")], use = "complete.obs")
```
```{r}
knitr::kable(round(cor_matrix, 3), caption = "Matriks Korelasi Pearson")
```
### Korelasi dengan Notasi Signifikansi
```{r}
add_significance <- function(cor_val, p_val) {
if (is.na(p_val)) return(sprintf("%.3f", cor_val))
if (p_val < 0.001) return(sprintf("%.3f***", cor_val))
if (p_val < 0.01) return(sprintf("%.3f**", cor_val))
if (p_val < 0.05) return(sprintf("%.3f*", cor_val))
sprintf("%.3f", cor_val)
}
cor_sig <- matrix(mapply(add_significance, as.vector(cor_matrix), as.vector(corr_pvalues$p)),
nrow = 3, dimnames = list(c("PEB", "OL", "CCS"), c("PEB", "OL", "CCS")))
knitr::kable(cor_sig, caption = "Korelasi dengan Notasi Signifikansi")
```
### Visualisasi Matriks Korelasi
```{r}
#| label: corr-plot
#| fig-width: 6
#| fig-height: 5.5
#| code-fold: true
#| code-summary: "Kode matriks korelasi"
# ---- Hitung korelasi & p-value ----
cor_vars <- c("PEB", "OL", "CCS")
cor_data_utama <- data_Fscores[, cor_vars]
cor_res <- psych::corr.test(cor_data_utama, use = "complete.obs")
cor_r <- round(cor_res$r, 2)
cor_p <- cor_res$p
# ---- Fungsi: nilai r + bintang signifikansi ----
add_significance <- function(cor_val, p_val) {
stars <- ifelse(p_val < .001, "***", ifelse(p_val < .01, "**",
ifelse(p_val < .05, "*", "")
))
paste0(sprintf("%.2f", cor_val), stars)
}
cor_sig_matrix <- matrix(
mapply(add_significance, as.vector(cor_r), as.vector(cor_p)),
nrow = length(cor_vars), ncol = length(cor_vars),
dimnames = list(cor_vars, cor_vars)
)
# ---- Long-format grid ----
cor_long <- expand.grid(
row = factor(cor_vars, levels = rev(cor_vars)),
col = factor(cor_vars, levels = cor_vars),
stringsAsFactors = FALSE
)
cor_long$r <- mapply(
function(r, c) cor_r[as.character(r), as.character(c)],
cor_long$row, cor_long$col
)
cor_long$sig <- mapply(
function(r, c) cor_sig_matrix[as.character(r), as.character(c)],
cor_long$row, cor_long$col
)
cor_long$row_i <- match(as.character(cor_long$row), cor_vars)
cor_long$col_i <- match(as.character(cor_long$col), cor_vars)
cor_long$panel <- ifelse(cor_long$row_i == cor_long$col_i, "diag",
ifelse(cor_long$row_i < cor_long$col_i, "upper", "lower")
)
cor_tile <- cor_long[cor_long$panel == "upper", ]
cor_diag <- cor_long[cor_long$panel == "diag", ]
# ---- Plot ----
p_corr <- ggplot(cor_long, aes(x = col, y = row)) +
# Grid putih untuk semua sel (border tipis)
geom_tile(fill = "white", color = "grey80", linewidth = 0.5) +
# Upper triangle — warna berdasarkan r
geom_tile(data = cor_tile, aes(fill = r), color = "white", linewidth = 0.5) +
# Nilai r + bintang (teks putih di atas tile)
geom_text(
data = cor_tile, aes(label = sig),
size = 5, fontface = "bold", color = "white"
) +
# Nama variabel di diagonal
geom_text(
data = cor_diag, aes(label = as.character(col)),
size = 5.5, fontface = "bold", color = "grey20"
) +
scale_fill_gradient2(
low = "#2166AC",
mid = "white",
high = "#B2182B",
midpoint = 0,
limits = c(-1, 1),
name = "Pearson r",
guide = guide_colorbar(
barwidth = 1.2, barheight = 8,
title.position = "top", title.hjust = 0.5
)
) +
scale_x_discrete(position = "top") +
labs(
title = "Pearson Correlation Matrix",
subtitle = paste0(
"Variabel utama: PEB, OL, CCS (standardized factor scores; N = ",
nrow(cor_data_utama), ")"
),
caption = "*** p < .001 ** p < .01 * p < .05 (two-tailed, adjusted for multiple comparisons)"
) +
theme_bw(base_size = 12) +
theme(
plot.title = element_text(face = "bold", size = 13, hjust = 0.5),
plot.subtitle = element_text(
size = 9.5, hjust = 0.5, color = "grey35",
margin = margin(b = 8)
),
plot.caption = element_text(
size = 8, color = "grey50", hjust = 0,
margin = margin(t = 8)
),
axis.text.x = element_text(size = 11, face = "bold"),
axis.text.y = element_text(size = 11, face = "bold"),
axis.title = element_blank(),
axis.ticks = element_blank(),
panel.border = element_rect(color = "grey70"),
panel.grid = element_blank(),
legend.title = element_text(face = "bold", size = 9),
legend.text = element_text(size = 8.5),
plot.margin = margin(15, 15, 10, 15)
)
print(p_corr)
```
::: {.callout-tip}
## Panduan Interpretasi
- **Notasi**: \*\*\* p<.001 | \*\* p<.01 | \* p<.05
- **Kekuatan** (Cohen, 1992): |r|<0.30 = Kecil | 0.30–0.49 = Sedang | ≥0.50 = Besar
:::