Load Dataset

library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.2.0     ✔ readr     2.1.6
## ✔ forcats   1.0.1     ✔ stringr   1.6.0
## ✔ ggplot2   4.0.2     ✔ tibble    3.3.1
## ✔ lubridate 1.9.5     ✔ tidyr     1.3.2
## ✔ purrr     1.2.1     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(dlookr)
## Registered S3 methods overwritten by 'dlookr':
##   method          from  
##   plot.transform  scales
##   print.transform scales
## 
## Attaching package: 'dlookr'
## 
## The following object is masked from 'package:tidyr':
## 
##     extract
## 
## The following object is masked from 'package:base':
## 
##     transform
# menentukan folder data
folderData <- "C:/Users/LUCKY SURYA/Documents/kuliah/semester 4/analisis multivariat/pertemuan 3 anmul"

# membaca data
data_udara <- read_delim(
  paste0(folderData, "/AirQualityUCI.csv"),
  delim = ";"
)
## Rows: 9357 Columns: 13
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ";"
## chr (4): CO(GT), C6H6(GT), T, AH
## dbl (8): PT08.S1(CO), NMHC(GT), PT08.S2(NMHC), NOx(GT), PT08.S3(NOx), NO2(GT...
## num (1): RH
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Mengubah koma menjadi titik

data_udara[] <- lapply(data_udara, function(x) as.numeric(gsub(",", ".", x)))
print((data_udara))
## # A tibble: 9,357 × 13
##    `CO(GT)` `PT08.S1(CO)` `NMHC(GT)` `C6H6(GT)` `PT08.S2(NMHC)` `NOx(GT)`
##       <dbl>         <dbl>      <dbl>      <dbl>           <dbl>     <dbl>
##  1      2.6          1360        150       11.9            1046       166
##  2      2            1292        112        9.4             955       103
##  3      2.2          1402         88        9               939       131
##  4      2.2          1376         80        9.2             948       172
##  5      1.6          1272         51        6.5             836       131
##  6      1.2          1197         38        4.7             750        89
##  7      1.2          1185         31        3.6             690        62
##  8      1            1136         31        3.3             672        62
##  9      0.9          1094         24        2.3             609        45
## 10      0.6          1010         19        1.7             561      -200
## # ℹ 9,347 more rows
## # ℹ 7 more variables: `PT08.S3(NOx)` <dbl>, `NO2(GT)` <dbl>,
## #   `PT08.S4(NO2)` <dbl>, `PT08.S5(O3)` <dbl>, T <dbl>, RH <dbl>, AH <dbl>
glimpse(data_udara)
## Rows: 9,357
## Columns: 13
## $ `CO(GT)`        <dbl> 2.6, 2.0, 2.2, 2.2, 1.6, 1.2, 1.2, 1.0, 0.9, 0.6, -200…
## $ `PT08.S1(CO)`   <dbl> 1360, 1292, 1402, 1376, 1272, 1197, 1185, 1136, 1094, …
## $ `NMHC(GT)`      <dbl> 150, 112, 88, 80, 51, 38, 31, 31, 24, 19, 14, 8, 16, 2…
## $ `C6H6(GT)`      <dbl> 11.9, 9.4, 9.0, 9.2, 6.5, 4.7, 3.6, 3.3, 2.3, 1.7, 1.3…
## $ `PT08.S2(NMHC)` <dbl> 1046, 955, 939, 948, 836, 750, 690, 672, 609, 561, 527…
## $ `NOx(GT)`       <dbl> 166, 103, 131, 172, 131, 89, 62, 62, 45, -200, 21, 16,…
## $ `PT08.S3(NOx)`  <dbl> 1056, 1174, 1140, 1092, 1205, 1337, 1462, 1453, 1579, …
## $ `NO2(GT)`       <dbl> 113, 92, 114, 122, 116, 96, 77, 76, 60, -200, 34, 28, …
## $ `PT08.S4(NO2)`  <dbl> 1692, 1559, 1555, 1584, 1490, 1393, 1333, 1333, 1276, …
## $ `PT08.S5(O3)`   <dbl> 1268, 972, 1074, 1203, 1110, 949, 733, 730, 620, 501, …
## $ T               <dbl> 13.6, 13.3, 11.9, 11.0, 11.2, 11.2, 11.3, 10.7, 10.7, …
## $ RH              <dbl> 489, 477, 54, 60, 596, 592, 568, 60, 597, 602, 605, 56…
## $ AH              <dbl> 0.7578, 0.7255, 0.7502, 0.7867, 0.7888, 0.7848, 0.7603…

karena bahasa r menerima data float menggunakan titik

Boxplot

data_udara %>%
  pivot_longer(cols = everything(),
               names_to = "Variabel",
               values_to = "Nilai") %>%
  ggplot(aes(x = Variabel, y = Nilai)) +
  geom_boxplot(fill = "orange") +
  coord_flip() +
  theme_minimal() +
  labs(title = "Boxplot Setiap Variabel",
       x = NULL,
       y = "Nilai")

berdasarkan hasil plot terdapat banyak outlier yang tersebar pada setiap fitur

Interpolasi

data_udara[data_udara == -200] <- NA

library(zoo)
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
data_udara <- data_udara %>%
  mutate(across(where(is.numeric), ~ na.approx(., na.rm = FALSE))) %>%
  mutate(across(where(is.numeric), ~ na.locf(., na.rm = FALSE))) %>%
  mutate(across(where(is.numeric), ~ na.locf(., fromLast = TRUE)))

pada dataset air quality sebagai data time series nilai dari -200 dianggap sebagai missing value sehingga cara penangannya yaitu di interpolasikan. JIka langsung di drop satu baris hal itu akan sangat mengurangi data yang berpengaruh ke dalam model.

Statistika Deskriptif

stat_deskriptif <- data.frame(
  Variabel = colnames(data_udara),
  Minimum = apply(data_udara, 2, min, na.rm = TRUE),
  Maksimum = apply(data_udara, 2, max, na.rm = TRUE),
  Mean = round(apply(data_udara, 2, mean, na.rm = TRUE), 3),
  Std_Dev = round(apply(data_udara, 2, sd, na.rm = TRUE), 3)
)

knitr::kable(
  stat_deskriptif,
  #caption = "Tabel 1. Statistika Deskriptif Variabel Penelitian"
)
Variabel Minimum Maksimum Mean Std_Dev
CO(GT) CO(GT) 0.1000 11.900 2.131 1.432
PT08.S1(CO) PT08.S1(CO) 647.0000 2040.000 1103.060 218.196
NMHC(GT) NMHC(GT) 7.0000 1189.000 269.834 74.252
C6H6(GT) C6H6(GT) 0.1000 63.700 10.179 7.504
PT08.S2(NMHC) PT08.S2(NMHC) 383.0000 2214.000 942.143 267.867
NOx(GT) NOx(GT) 2.0000 1479.000 241.922 204.315
PT08.S3(NOx) PT08.S3(NOx) 322.0000 2683.000 832.759 255.710
NO2(GT) NO2(GT) 2.0000 340.000 109.632 46.462
PT08.S4(NO2) PT08.S4(NO2) 551.0000 2775.000 1453.299 343.206
PT08.S5(O3) PT08.S5(O3) 221.0000 2523.000 1032.544 404.448
T T -1.9000 44.600 18.233 8.782
RH RH 10.0000 887.000 445.885 209.655
AH AH 0.1847 2.231 1.020 0.402

Scaling (standardisasi data)

data_skala <- scale(data_udara)
head(data_skala)
##           CO(GT) PT08.S1(CO)  NMHC(GT)   C6H6(GT) PT08.S2(NMHC)    NOx(GT)
## [1,]  0.32785179   1.1775644 -1.613887  0.2293295    0.38772051 -0.3715937
## [2,] -0.09121985   0.8659185 -2.125658 -0.1038345    0.04799919 -0.6799410
## [3,]  0.04847069   1.3700516 -2.448882 -0.1571408   -0.01173204 -0.5428978
## [4,]  0.04847069   1.2508929 -2.556623 -0.1304876    0.02186678 -0.3422273
## [5,] -0.37060094   0.7742580 -2.947185 -0.4903048   -0.39625178 -0.5428978
## [6,] -0.64998204   0.4305309 -3.122264 -0.7301829   -0.71730709 -0.7484626
##      PT08.S3(NOx)     NO2(GT) PT08.S4(NO2) PT08.S5(O3)          T         RH
## [1,]    0.8730251  0.07248685    0.6955039   0.5821661 -0.5276154  0.2056493
## [2,]    1.3344856 -0.37949239    0.3079816  -0.1496963 -0.5617770  0.1484123
## [3,]    1.2015224  0.09400967    0.2963268   0.1024996 -0.7211978 -1.8691921
## [4,]    1.0138097  0.26619223    0.3808242   0.4214531 -0.8236825 -1.8405736
## [5,]    1.4557168  0.13705531    0.1069363   0.1915098 -0.8009081  0.7160126
## [6,]    1.9719269 -0.29340111   -0.1756927  -0.2065640 -0.8009081  0.6969336
##              AH
## [1,] -0.6509669
## [2,] -0.7312746
## [3,] -0.6698628
## [4,] -0.5791126
## [5,] -0.5738914
## [6,] -0.5838366
knitr::kable(
  round(head(data_skala, 5), 2)
)
CO(GT) PT08.S1(CO) NMHC(GT) C6H6(GT) PT08.S2(NMHC) NOx(GT) PT08.S3(NOx) NO2(GT) PT08.S4(NO2) PT08.S5(O3) T RH AH
0.33 1.18 -1.61 0.23 0.39 -0.37 0.87 0.07 0.70 0.58 -0.53 0.21 -0.65
-0.09 0.87 -2.13 -0.10 0.05 -0.68 1.33 -0.38 0.31 -0.15 -0.56 0.15 -0.73
0.05 1.37 -2.45 -0.16 -0.01 -0.54 1.20 0.09 0.30 0.10 -0.72 -1.87 -0.67
0.05 1.25 -2.56 -0.13 0.02 -0.34 1.01 0.27 0.38 0.42 -0.82 -1.84 -0.58
-0.37 0.77 -2.95 -0.49 -0.40 -0.54 1.46 0.14 0.11 0.19 -0.80 0.72 -0.57

Uji Korelasi Pearson

library(corrr)
## 
## Attaching package: 'corrr'
## The following object is masked from 'package:dlookr':
## 
##     correlate
library(ggcorrplot)

matriks_korelasi <- cor(data_skala)
ggcorrplot(matriks_korelasi, lab = TRUE, lab_size = 3, type = "full")
## Warning: `aes_string()` was deprecated in ggplot2 3.0.0.
## ℹ Please use tidy evaluation idioms with `aes()`.
## ℹ See also `vignette("ggplot2-in-packages")` for more information.
## ℹ The deprecated feature was likely used in the ggcorrplot package.
##   Please report the issue at <https://github.com/kassambara/ggcorrplot/issues>.
## This warning is displayed once per session.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

dari heatmap tersebut bisa diambil kesimpulan bahwa matriks tersbut masih cukup layak karena banyak korelasi cukup tinggi antar variabel

PCA (Principal Component Analysis)

pca_udara <- princomp(data_skala)

pca_summary <- data.frame(
  Komponen = paste0("PC", 1:length(pca_udara$sdev)),
  `Standard Deviation` = round(pca_udara$sdev, 4),
  `Proportion Variance` = round(pca_udara$sdev^2 / sum(pca_udara$sdev^2), 4),
  `Cumulative Variance` = round(cumsum(pca_udara$sdev^2 / sum(pca_udara$sdev^2)), 4)
)

knitr::kable(pca_summary)
Komponen Standard.Deviation Proportion.Variance Cumulative.Variance
Comp.1 PC1 2.6037 0.5215 0.5215
Comp.2 PC2 1.5581 0.1868 0.7083
Comp.3 PC3 1.1117 0.0951 0.8034
Comp.4 PC4 0.9631 0.0714 0.8747
Comp.5 PC5 0.7014 0.0379 0.9126
Comp.6 PC6 0.6302 0.0306 0.9432
Comp.7 PC7 0.4683 0.0169 0.9600
Comp.8 PC8 0.3920 0.0118 0.9719
Comp.9 PC9 0.3627 0.0101 0.9820
Comp.10 PC10 0.3161 0.0077 0.9897
Comp.11 PC11 0.2857 0.0063 0.9959
Comp.12 PC12 0.2081 0.0033 0.9993
Comp.13 PC13 0.0972 0.0007 1.0000
pca_udara$loadings[, 1:3]
##                     Comp.1      Comp.2       Comp.3
## CO(GT)         0.340975797  0.07399541  0.001324948
## PT08.S1(CO)    0.359092780  0.01586722 -0.066706932
## NMHC(GT)       0.112437912 -0.03756398  0.144250317
## C6H6(GT)       0.362874010 -0.06753631  0.047210868
## PT08.S2(NMHC)  0.368747904 -0.08129517  0.064517730
## NOx(GT)        0.297159899  0.27876215 -0.052904531
## PT08.S3(NOx)  -0.326695996  0.01498722  0.036013305
## NO2(GT)        0.273683169  0.31184602  0.225861539
## PT08.S4(NO2)   0.267100529 -0.40869590 -0.118403515
## PT08.S5(O3)    0.357056411  0.08614507 -0.060690693
## T              0.045864701 -0.56836652  0.253997995
## RH             0.006864794  0.14714273 -0.844480377
## AH             0.059779663 -0.53606540 -0.343328921
loadings_pca3 <- as.data.frame(unclass(pca_udara$loadings[,1:3]))

knitr::kable(
  round(loadings_pca3, 3)
  
)
Comp.1 Comp.2 Comp.3
CO(GT) 0.341 0.074 0.001
PT08.S1(CO) 0.359 0.016 -0.067
NMHC(GT) 0.112 -0.038 0.144
C6H6(GT) 0.363 -0.068 0.047
PT08.S2(NMHC) 0.369 -0.081 0.065
NOx(GT) 0.297 0.279 -0.053
PT08.S3(NOx) -0.327 0.015 0.036
NO2(GT) 0.274 0.312 0.226
PT08.S4(NO2) 0.267 -0.409 -0.118
PT08.S5(O3) 0.357 0.086 -0.061
T 0.046 -0.568 0.254
RH 0.007 0.147 -0.844
AH 0.060 -0.536 -0.343

Scree Plot

screeplot(pca_udara, type = "l", npcs = 12, main = "Screeplot Komponen Utama")
abline(h = 1, col="red", lty=5)
legend("topright", legend=c("Eigenvalue = 1"),
       col=c("red"), lty=5, cex=0.6)

skor_pca <- as.data.frame(pca_udara$scores[,1:3])
names(skor_pca)[1] <- "PC1"
names(skor_pca)[2] <- "PC2"
names(skor_pca)[3] <- "PC3"

write_csv(skor_pca, "skor_pca_kualitas_udara.csv")

Biplot PCA

library(factoextra)
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
fviz_pca_biplot(pca_udara, label = "var", axes = 1:2,addEllipses=TRUE, ellipse.level=0.95)
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## ℹ The deprecated feature was likely used in the ggpubr package.
##   Please report the issue at <https://github.com/kassambara/ggpubr/issues>.
## This warning is displayed once per session.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

Kontribusi Variabel

library(factoextra)

# Kontribusi variabel terhadap PC1
fviz_contrib(pca_udara, choice = "var", axes = 1, top = 10)

# Kontribusi variabel terhadap PC2
fviz_contrib(pca_udara, choice = "var", axes = 2, top = 10)

# Kontribusi variabel terhadap PC3
fviz_contrib(pca_udara, choice = "var", axes = 3, top = 10)

Visualisasi Varaibel PCA

#| fig.width: 6
#| fig.height: 5
fviz_pca_var(pca_udara, col.var = "cos2",
             gradient.cols = c("black", "orange", "green"),
             repel = TRUE)

FA (Factor Analysis)

library(psych)
## 
## Attaching package: 'psych'
## The following object is masked from 'package:dlookr':
## 
##     describe
## The following objects are masked from 'package:ggplot2':
## 
##     %+%, alpha
data_bersih <- data_skala[, colnames(data_skala) != "NMHC(GT)"]

R2 <- cor(data_bersih)

KMO(R2)
## Kaiser-Meyer-Olkin factor adequacy
## Call: KMO(r = R2)
## Overall MSA =  0.82
## MSA for each item = 
##        CO(GT)   PT08.S1(CO)      C6H6(GT) PT08.S2(NMHC)       NOx(GT) 
##          0.91          0.94          0.84          0.79          0.81 
##  PT08.S3(NOx)       NO2(GT)  PT08.S4(NO2)   PT08.S5(O3)             T 
##          0.82          0.89          0.75          0.95          0.57 
##            RH            AH 
##          0.36          0.44
fa_result <- fa(R2,
                nfactors = 2,
                fm = "pa",
                rotate = "varimax")
kmo_result <- KMO(R2)

kmo_table <- data.frame(
  Variabel = names(kmo_result$MSAi),
  MSA = round(kmo_result$MSAi,3)
)
uji_barlets<-cortest.bartlett(R2, n = nrow(data_bersih))
knitr::kable(
  kmo_table,
  #caption = "Tabel 3. Nilai MSA Tiap Variabel"
)
Variabel MSA
CO(GT) CO(GT) 0.913
PT08.S1(CO) PT08.S1(CO) 0.943
C6H6(GT) C6H6(GT) 0.838
PT08.S2(NMHC) PT08.S2(NMHC) 0.787
NOx(GT) NOx(GT) 0.812
PT08.S3(NOx) PT08.S3(NOx) 0.816
NO2(GT) NO2(GT) 0.890
PT08.S4(NO2) PT08.S4(NO2) 0.752
PT08.S5(O3) PT08.S5(O3) 0.945
T T 0.574
RH RH 0.360
AH AH 0.438
knitr::kable(
  uji_barlets,
  #caption = "Tabel 3. Nilai MSA Tiap Variabel"
)
x
155100.1
x
0
x
66

Scree Plot FA

scree(data_skala, pc = FALSE)

Parallel Analysis

fa.parallel(data_skala)

## Parallel analysis suggests that the number of factors =  5  and the number of components =  3

Ekstrasi Faktor

hasil_fa <- fa(r = data_skala,
               nfactors = 2,
               fm = "pa",
               rotate = "varimax")

print(hasil_fa, sort = TRUE)
## Factor Analysis using method =  pa
## Call: fa(r = data_skala, nfactors = 2, rotate = "varimax", fm = "pa")
## Standardized loadings (pattern matrix) based upon correlation matrix
##               item   PA1   PA2    h2    u2 com
## PT08.S2(NMHC)    5  0.95  0.22 0.950 0.050 1.1
## PT08.S5(O3)     10  0.93 -0.05 0.875 0.125 1.0
## C6H6(GT)         4  0.93  0.19 0.903 0.097 1.1
## PT08.S1(CO)      2  0.93  0.06 0.863 0.137 1.0
## CO(GT)           1  0.88 -0.04 0.768 0.232 1.0
## PT08.S3(NOx)     7 -0.82 -0.09 0.673 0.327 1.0
## NOx(GT)          6  0.79 -0.35 0.747 0.253 1.4
## NO2(GT)          8  0.73 -0.40 0.691 0.309 1.6
## NMHC(GT)         3  0.25  0.06 0.067 0.933 1.1
## T               11  0.04  0.81 0.660 0.340 1.0
## AH              13  0.08  0.76 0.585 0.415 1.0
## PT08.S4(NO2)     9  0.63  0.72 0.921 0.079 2.0
## RH              12  0.03 -0.14 0.021 0.979 1.1
## 
##                        PA1  PA2
## SS loadings           6.56 2.16
## Proportion Var        0.50 0.17
## Cumulative Var        0.50 0.67
## Proportion Explained  0.75 0.25
## Cumulative Proportion 0.75 1.00
## 
## Mean item complexity =  1.2
## Test of the hypothesis that 2 factors are sufficient.
## 
## df null model =  78  with the objective function =  16.72 with Chi Square =  156367
## df of  the model are 53  and the objective function was  3.75 
## 
## The root mean square of the residuals (RMSR) is  0.06 
## The df corrected root mean square of the residuals is  0.08 
## 
## The harmonic n.obs is  9357 with the empirical chi square  2829.06  with prob <  0 
## The total n.obs was  9357  with Likelihood Chi Square =  35025.16  with prob <  0 
## 
## Tucker Lewis Index of factoring reliability =  0.671
## RMSEA index =  0.266  and the 90 % confidence intervals are  0.263 0.268
## BIC =  34540.54
## Fit based upon off diagonal values = 0.99
## Measures of factor score adequacy             
##                                                    PA1  PA2
## Correlation of (regression) scores with factors   0.99 0.96
## Multiple R square of scores with factors          0.98 0.91
## Minimum correlation of possible factor scores     0.96 0.83
loading_fa <- as.data.frame(unclass(hasil_fa$loadings[,1:2]))

knitr::kable(
  round(loading_fa,3),
  #caption = "Tabel 4. Loading Faktor"
)
PA1 PA2
CO(GT) 0.876 -0.036
PT08.S1(CO) 0.927 0.060
NMHC(GT) 0.251 0.058
C6H6(GT) 0.931 0.191
PT08.S2(NMHC) 0.951 0.216
NOx(GT) 0.790 -0.350
PT08.S3(NOx) -0.815 -0.090
NO2(GT) 0.729 -0.400
PT08.S4(NO2) 0.633 0.721
PT08.S5(O3) 0.934 -0.052
T 0.040 0.811
RH 0.029 -0.143
AH 0.078 0.761

Diagram Faktor

fa.diagram(hasil_fa)

Alternatif dengan Factanal

hasil_factanal <- factanal(data_skala,
                           factors = 2,
                           scores = "Bartlett",
                           rotation = "varimax")

print(hasil_factanal, sort = TRUE)
## 
## Call:
## factanal(x = data_skala, factors = 2, scores = "Bartlett", rotation = "varimax")
## 
## Uniquenesses:
##        CO(GT)   PT08.S1(CO)      NMHC(GT)      C6H6(GT) PT08.S2(NMHC) 
##         0.277         0.168         0.943         0.031         0.012 
##       NOx(GT)  PT08.S3(NOx)       NO2(GT)  PT08.S4(NO2)   PT08.S5(O3) 
##         0.284         0.360         0.296         0.087         0.160 
##             T            RH            AH 
##         0.419         0.987         0.402 
## 
## Loadings:
##               Factor1 Factor2
## CO(GT)         0.849         
## PT08.S1(CO)    0.898   0.158 
## C6H6(GT)       0.941   0.290 
## PT08.S2(NMHC)  0.947   0.302 
## NOx(GT)        0.790  -0.304 
## PT08.S3(NOx)  -0.792  -0.117 
## NO2(GT)        0.751  -0.375 
## PT08.S5(O3)    0.916         
## PT08.S4(NO2)   0.567   0.769 
## T                      0.762 
## AH                     0.772 
## NMHC(GT)       0.232         
## RH                    -0.112 
## 
##                Factor1 Factor2
## SS loadings      6.341   2.235
## Proportion Var   0.488   0.172
## Cumulative Var   0.488   0.660
## 
## Test of the hypothesis that 2 factors are sufficient.
## The chi square statistic is 31486.52 on 53 degrees of freedom.
## The p-value is 0

Matriks Loading dalam bentuk Tidy

matriks_loading <- broom::tidy(hasil_factanal) %>%
  pivot_longer(starts_with("fl"),
               names_to = "faktor",
               values_to = "loading")

Heatmap Loading

fa_loading_plot <- ggplot(matriks_loading,
                          aes(x = faktor, y = variable, fill = loading)) +
  geom_tile() +
  labs(title = "Loading Faktor",
       x = NULL,
       y = NULL) +
  scico::scale_fill_scico(palette = "cork", limits = c(-1,1)) +
  coord_fixed(ratio = 1/2)

print(fa_loading_plot)

Korelasi Skor Faktor

hasil_factanal$scores %>%
  cor() %>%
  data.frame() %>%
  rownames_to_column("faktor_x") %>%
  pivot_longer(cols = -faktor_x,
               names_to = "faktor_y",
               values_to = "korelasi") %>%
  ggplot(aes(x = faktor_x, y = faktor_y, fill = korelasi)) +
  geom_tile() +
  geom_text(aes(label = round(korelasi,4)), color = "white") +
  labs(title = "Korelasi antar Skor Faktor",
       x = NULL,
       y = NULL) +
  scico::scale_fill_scico(palette = "berlin", limits = c(-1,1)) +
  coord_equal()