# Load semua library yang dibutuhkan
library(tidyverse)      # Data manipulation & visualisasi
library(corrplot)       # Visualisasi korelasi
library(ggplot2)        # Plot lanjutan
library(GGally)         # Pairplot
library(caret)          # Feature selection (RFE, VIF)
library(randomForest)   # Feature importance (Boruta / RF-based)
library(Boruta)         # Boruta feature selection
library(factoextra)     # Visualisasi PCA
library(FactoMineR)     # PCA
library(psych)          # Statistik deskriptif lanjutan
library(car)            # VIF untuk multikolinearitas
library(gridExtra)      # Gabungkan plot
library(scales)         # Format axis
library(knitr)          # Table knitr
library(kableExtra)     # Tabel estetis
library(e1071)          # Skewness & kurtosis

1 Deskripsi Dataset

1.1 Sumber Dataset

Dataset yang digunakan dalam analisis ini adalah US Economic Dataset, sebuah dataset yang menggabungkan data indikator ekonomi makro Amerika Serikat dari berbagai sumber, meliputi:

  • House Price Index (HPI) dari Federal Housing Finance Agency (FHFA), yang mencerminkan pergerakan harga properti residensial di berbagai wilayah/divisi sensus Amerika Serikat.
  • Indikator IMF World Economic Outlook, mencakup data GDP, inflasi, pengangguran, dan neraca perdagangan.
  • S&P 500 Index (GSPC.Close), yang merepresentasikan pergerakan pasar modal Amerika Serikat.

Data mencakup rentang waktu Januari 1991 hingga Desember 2023, dengan frekuensi bulanan.

# Load dataset
df <- read.csv("USDataset.csv", stringsAsFactors = FALSE)

# Tampilkan 6 baris pertama
head(df) %>%
  kable(caption = "Enam Baris Pertama Dataset") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
                full_width = TRUE)%>%
  scroll_box(width = "100%", height = "300px")
Enam Baris Pertama Dataset
hpi_type hpi_flavor frequency level place_name place_id yr period index_nsa index_sa Gross.domestic.product..constant.prices Gross.domestic.product.per.capita..constant.prices Gross.domestic.product.per.capita..current.prices Gross.domestic.product.based.on.purchasing.power.parity..PPP..share.of.world.total Inflation..average.consumer.prices Volume.of.imports.of.goods.and.services Volume.of.exports.of.goods.and.services Unemployment.rate Current.account.balance Date GSPC.Close
traditional purchase-only monthly USA or Census Division East North Central Division DV_ENC 1991 1 100.00 100.00 -0.108 36944.07 24302.78 20.985 4.216 -0.151 6.612 6.85 0.047 01-01-1991 343.93
traditional purchase-only monthly USA or Census Division East North Central Division DV_ENC 1991 2 100.89 100.95 -0.108 36944.07 24302.78 20.985 4.216 -0.151 6.612 6.85 0.047 01-02-1991 367.07
traditional purchase-only monthly USA or Census Division East North Central Division DV_ENC 1991 3 101.30 100.92 -0.108 36944.07 24302.78 20.985 4.216 -0.151 6.612 6.85 0.047 01-03-1991 375.22
traditional purchase-only monthly USA or Census Division East North Central Division DV_ENC 1991 4 101.69 100.98 -0.108 36944.07 24302.78 20.985 4.216 -0.151 6.612 6.85 0.047 01-04-1991 375.34
traditional purchase-only monthly USA or Census Division East North Central Division DV_ENC 1991 5 102.31 101.36 -0.108 36944.07 24302.78 20.985 4.216 -0.151 6.612 6.85 0.047 01-05-1991 389.83
traditional purchase-only monthly USA or Census Division East North Central Division DV_ENC 1991 6 102.77 101.50 -0.108 36944.07 24302.78 20.985 4.216 -0.151 6.612 6.85 0.047 01-06-1991 371.16

1.2 Jumlah Observasi dan Variabel

cat("=== INFORMASI UMUM DATASET ===\n")
## === INFORMASI UMUM DATASET ===
cat("Jumlah Observasi (Baris) :", nrow(df), "\n")
## Jumlah Observasi (Baris) : 6570
cat("Jumlah Variabel (Kolom)  :", ncol(df), "\n")
## Jumlah Variabel (Kolom)  : 21
cat("\nDaftar Variabel:\n")
## 
## Daftar Variabel:
print(names(df))
##  [1] "hpi_type"                                                                          
##  [2] "hpi_flavor"                                                                        
##  [3] "frequency"                                                                         
##  [4] "level"                                                                             
##  [5] "place_name"                                                                        
##  [6] "place_id"                                                                          
##  [7] "yr"                                                                                
##  [8] "period"                                                                            
##  [9] "index_nsa"                                                                         
## [10] "index_sa"                                                                          
## [11] "Gross.domestic.product..constant.prices"                                           
## [12] "Gross.domestic.product.per.capita..constant.prices"                                
## [13] "Gross.domestic.product.per.capita..current.prices"                                 
## [14] "Gross.domestic.product.based.on.purchasing.power.parity..PPP..share.of.world.total"
## [15] "Inflation..average.consumer.prices"                                                
## [16] "Volume.of.imports.of.goods.and.services"                                           
## [17] "Volume.of.exports.of.goods.and.services"                                           
## [18] "Unemployment.rate"                                                                 
## [19] "Current.account.balance"                                                           
## [20] "Date"                                                                              
## [21] "GSPC.Close"

Ringkasan:

Atribut Keterangan
Jumlah Observasi 6.570 baris
Jumlah Variabel 21 kolom
Rentang Waktu Januari 1991 – Desember 2023
Frekuensi Bulanan
Cakupan Wilayah 10 wilayah (9 Divisi Sensus + United States)

1.3 Tujuan Analisis

Tujuan utama analisis ini adalah melakukan data reduction pada dataset ekonomi Amerika Serikat melalui serangkaian tahapan:

  1. EDA (Exploratory Data Analysis) – Memahami distribusi, korelasi, outlier, dan multikolinearitas antar variabel.
  2. Feature Engineering – Membuat fitur-fitur baru yang lebih informatif dari variabel yang ada.
  3. Feature Selection – Memilih variabel paling relevan menggunakan minimal 2 metode seleksi fitur.
  4. Feature Extraction (PCA) – Mereduksi dimensi menggunakan Principal Component Analysis.
  5. Insight dan Kesimpulan – Mengidentifikasi variabel paling penting, mengevaluasi keberhasilan reduksi dimensi, dan menginterpretasikan makna substantif dari komponen utama.

2 Exploratory Data Analysis (EDA)

2.1 Statistik Deskriptif

Pada bagian ini, kami menyajikan statistik deskriptif untuk seluruh variabel numerik dalam dataset. Statistik deskriptif mencakup nilai rata-rata, median, standar deviasi, nilai minimum dan maksimum, serta ukuran kemiringan (skewness) dan kurtosis.

# Pilih hanya kolom numerik yang relevan untuk analisis
numeric_cols <- c("index_nsa", "index_sa",
                  "Gross.domestic.product..constant.prices",
                  "Gross.domestic.product.per.capita..constant.prices",
                  "Gross.domestic.product.per.capita..current.prices",
                  "Gross.domestic.product.based.on.purchasing.power.parity..PPP..share.of.world.total",
                  "Inflation..average.consumer.prices",
                  "Volume.of.imports.of.goods.and.services",
                  "Volume.of.exports.of.goods.and.services",
                  "Unemployment.rate",
                  "Current.account.balance",
                  "GSPC.Close")

# Buat nama pendek untuk kemudahan
short_names <- c("HPI_NSA", "HPI_SA", "GDP_Const", "GDP_PC_Const",
                 "GDP_PC_Curr", "GDP_PPP_Share",
                 "Inflation", "Imports", "Exports",
                 "Unemployment", "Current_Acc", "SP500")

df_num <- df[, numeric_cols]
colnames(df_num) <- short_names
# Statistik deskriptif lengkap
desc_stats <- data.frame(
  Variabel    = short_names,
  N           = sapply(df_num, function(x) sum(!is.na(x))),
  Mean        = sapply(df_num, mean, na.rm = TRUE),
  Median      = sapply(df_num, median, na.rm = TRUE),
  SD          = sapply(df_num, sd, na.rm = TRUE),
  Min         = sapply(df_num, min, na.rm = TRUE),
  Max         = sapply(df_num, max, na.rm = TRUE),
  Skewness    = sapply(df_num, e1071::skewness, na.rm = TRUE),
  Kurtosis    = sapply(df_num, e1071::kurtosis, na.rm = TRUE)
)

desc_stats[, 3:9] <- round(desc_stats[, 3:9], 3)

desc_stats %>%
  kable(caption = "Statistik Deskriptif Variabel Numerik",
        row.names = FALSE) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
                full_width = TRUE, font_size = 12)
Statistik Deskriptif Variabel Numerik
Variabel N Mean Median SD Min Max Skewness Kurtosis
HPI_NSA 6570 198.131 189.445 82.090 93.310 599.290 1.379 2.733
HPI_SA 6570 197.095 188.960 81.480 93.510 592.740 1.377 2.728
GDP_Const 6570 2.408 2.684 1.809 -2.768 5.947 -1.049 1.748
GDP_PC_Const 6570 49310.013 50523.500 6596.015 36944.070 60963.650 -0.249 -0.840
GDP_PC_Curr 6570 46474.926 47102.430 14707.573 24302.780 80412.410 0.375 -0.646
GDP_PPP_Share 6570 17.957 17.980 1.875 15.418 20.985 0.006 -1.704
Inflation 6570 2.601 2.596 1.426 -0.320 7.986 1.302 4.337
Imports 6570 5.055 5.160 6.191 -12.610 14.134 -0.792 0.615
Exports 6570 4.227 4.985 5.529 -13.235 12.882 -1.192 1.649
Unemployment 6570 5.777 5.408 1.638 3.569 9.608 0.772 -0.284
Current_Acc 6570 -2.892 -2.623 1.417 -5.911 0.047 -0.395 -0.420
SP500 6570 1597.092 1286.370 1056.880 343.930 4766.180 1.252 0.855

Interpretasi:

  • HPI (House Price Index): Nilai index_nsa dan index_sa memiliki distribusi yang positif (skewed right), menunjukkan kenaikan harga properti yang signifikan selama periode observasi.
  • GDP: Variabel GDP menunjukkan tren pertumbuhan positif. GDP per kapita saat ini (current prices) memiliki nilai lebih tinggi karena tidak disesuaikan inflasi.
  • Inflasi: Rata-rata inflasi sekitar 2.5–3%, dengan nilai maksimum mencapai ~8% (periode 2022).
  • Unemployment: Rata-rata pengangguran sekitar 6%, dengan puncak saat krisis 2008–2009 dan pandemi 2020.
  • S&P 500: Memiliki skewness positif dan kurtosis tinggi, yang mencerminkan pertumbuhan eksponensial pasar saham.

2.2 Visualisasi

2.2.1 Distribusi Variabel

df_long <- df_num %>%
  pivot_longer(everything(), names_to = "Variable", values_to = "Value")

ggplot(df_long, aes(x = Value, fill = Variable)) +
  geom_histogram(bins = 40, color = "white", alpha = 0.8) +
  facet_wrap(~ Variable, scales = "free", ncol = 3) +
  scale_fill_viridis_d() +
  theme_minimal(base_size = 11) +
  theme(legend.position = "none",
        strip.text = element_text(face = "bold"),
        plot.title = element_text(face = "bold", hjust = 0.5)) +
  labs(title = "Distribusi Setiap Variabel Numerik",
       x = "Nilai", y = "Frekuensi")

Interpretasi: Sebagian besar variabel menunjukkan distribusi tidak normal (non-Gaussian). HPI, GDP, dan S&P 500 memiliki distribusi right-skewed karena pertumbuhan ekonomi yang konsisten. Inflasi dan unemployment memiliki distribusi yang lebih bervariasi akibat siklus ekonomi.

2.2.2 Tren Waktu Variabel Utama

# Gunakan data United States saja untuk plot tren waktu
df_us <- df %>% filter(place_name == "United States") %>%
  mutate(Date_parsed = as.Date(paste(yr, period, "01", sep = "-"),
                                format = "%Y-%m-%d"))

colnames(df_us)[match(numeric_cols, colnames(df_us))] <- short_names

p1 <- ggplot(df_us, aes(x = Date_parsed, y = HPI_NSA)) +
  geom_line(color = "#2196F3", linewidth = 0.8) +
  theme_minimal() +
  labs(title = "House Price Index (NSA)", x = "Tahun", y = "HPI")

p2 <- ggplot(df_us, aes(x = Date_parsed, y = SP500)) +
  geom_line(color = "#4CAF50", linewidth = 0.8) +
  theme_minimal() +
  labs(title = "S&P 500 Close", x = "Tahun", y = "Indeks")

p3 <- ggplot(df_us, aes(x = Date_parsed, y = Unemployment)) +
  geom_line(color = "#F44336", linewidth = 0.8) +
  theme_minimal() +
  labs(title = "Unemployment Rate (%)", x = "Tahun", y = "%")

p4 <- ggplot(df_us, aes(x = Date_parsed, y = Inflation)) +
  geom_line(color = "#FF9800", linewidth = 0.8) +
  theme_minimal() +
  labs(title = "Inflation Rate (%)", x = "Tahun", y = "%")

grid.arrange(p1, p2, p3, p4, ncol = 2,
             top = "Tren Waktu Indikator Ekonomi Utama AS (1991–2023)")

Interpretasi: Dari plot tren waktu terlihat:

  • HPI & S&P 500 menunjukkan tren naik jangka panjang dengan dua koreksi besar (2008 dan 2020).
  • Unemployment melonjak tajam pada krisis 2008–2009 (~10%) dan pandemi 2020 (~15%).
  • Inflasi relatif stabil di bawah 4% kecuali lonjakan 2022 pasca pandemi.

2.3 Analisis Korelasi

cor_matrix <- cor(df_num, use = "complete.obs")

corrplot(cor_matrix,
         method = "color",
         type = "upper",
         order = "hclust",
         tl.cex = 0.8,
         tl.col = "black",
         addCoef.col = "black",
         number.cex = 0.65,
         col = colorRampPalette(c("#D32F2F", "white", "#1976D2"))(200),
         title = "Matriks Korelasi Variabel Numerik",
         mar = c(0,0,2,0))

Interpretasi:

  • HPI (NSA & SA) berkorelasi sangat tinggi satu sama lain (r ≈ 0.99), artinya kedua variabel hampir identik.
  • GDP dan GDP per kapita berkorelasi sangat tinggi (r > 0.95), mengindikasikan multikolinearitas kuat.
  • S&P 500 berkorelasi positif kuat dengan HPI dan GDP (r > 0.90), menunjukkan hubungan erat antara pasar keuangan dan ekonomi riil.
  • Unemployment berkorelasi negatif sedang dengan GDP dan S&P 500 (r ≈ -0.5 s.d. -0.7).

2.4 Identifikasi Multikolinearitas

Multikolinearitas terjadi ketika dua atau lebih variabel prediktor memiliki korelasi sangat tinggi. Hal ini dapat mengganggu estimasi model dan menjadi alasan utama dilakukannya reduksi dimensi.

# Buat model linier sederhana untuk menghitung VIF
# Gunakan HPI_NSA sebagai target sementara
lm_model <- lm(HPI_NSA ~ HPI_SA + GDP_Const + GDP_PC_Const +
                 GDP_PC_Curr + GDP_PPP_Share + Inflation +
                 Imports + Exports + Unemployment +
                 Current_Acc + SP500,
               data = df_num)

vif_values <- car::vif(lm_model)

vif_df <- data.frame(
  Variabel = names(vif_values),
  VIF = round(vif_values, 2),
  Kategori = ifelse(vif_values > 10, "Multikolinear Tinggi",
              ifelse(vif_values > 5, "Moderate",
                     "Rendah"))
)

vif_df %>%
  arrange(desc(VIF)) %>%
  kable(caption = "Variance Inflation Factor (VIF)",
        row.names = FALSE) %>%
  kable_styling(bootstrap_options = c("striped", "hover"),
                full_width = FALSE) %>%
  row_spec(which(vif_df$VIF > 10), background = "#FFEBEE")
Variance Inflation Factor (VIF)
Variabel VIF Kategori
GDP_PC_Curr 205.42 Multikolinear Tinggi
GDP_PC_Const 140.33 Multikolinear Tinggi
GDP_PPP_Share 35.68 Multikolinear Tinggi
SP500 34.18 Multikolinear Tinggi
Imports 11.75 Multikolinear Tinggi
GDP_Const 9.03 Moderate
Current_Acc 8.26 Moderate
HPI_SA 7.43 Moderate
Exports 6.18 Moderate
Inflation 4.65 Rendah
Unemployment 4.20 Rendah

Interpretasi: Variabel dengan VIF > 10 mengalami multikolinearitas serius. GDP dan turunannya (GDP per kapita, GDP PPP) serta HPI_SA hampir pasti memiliki VIF sangat tinggi karena saling berkorelasi kuat. Kondisi ini mengkonfirmasi perlunya reduksi dimensi.

2.5 Missing Value & Outlier

# Cek missing values
cat("=== MISSING VALUES ===\n")
## === MISSING VALUES ===
missing_count <- colSums(is.na(df_num))
print(missing_count)
##       HPI_NSA        HPI_SA     GDP_Const  GDP_PC_Const   GDP_PC_Curr 
##             0             0             0             0             0 
## GDP_PPP_Share     Inflation       Imports       Exports  Unemployment 
##             0             0             0             0             0 
##   Current_Acc         SP500 
##             0             0
cat("\nTotal missing values:", sum(missing_count), "\n")
## 
## Total missing values: 0
# Boxplot untuk deteksi outlier
df_scaled_long <- as.data.frame(scale(df_num)) %>%
  pivot_longer(everything(), names_to = "Variable", values_to = "Z_Score")

ggplot(df_scaled_long, aes(x = Variable, y = Z_Score, fill = Variable)) +
  geom_boxplot(alpha = 0.7, outlier.color = "red", outlier.size = 0.8) +
  coord_flip() +
  scale_fill_viridis_d() +
  theme_minimal(base_size = 11) +
  theme(legend.position = "none",
        plot.title = element_text(face = "bold", hjust = 0.5)) +
  labs(title = "Deteksi Outlier via Boxplot (Z-Score)",
       x = "Variabel", y = "Z-Score")

Interpretasi:

  • Tidak ada missing values pada seluruh 21 kolom – dataset sudah bersih.
  • Outlier terdeteksi pada beberapa variabel, terutama Inflation (lonjakan 2022) dan Unemployment (lonjakan pandemi 2020). Outlier ini bersifat valid secara kontekstual (bukan error data), sehingga tidak dihapus tetapi perlu diperhatikan dalam interpretasi PCA.

3 Feature Engineering

Pada tahap ini, kami membuat minimal 3 fitur baru yang lebih informatif dari variabel yang telah ada. Fitur-fitur ini dirancang berdasarkan pemahaman ekonomi makro.

# Gunakan data United States saja untuk feature engineering
df_fe <- df %>%
  filter(place_name == "United States") %>%
  arrange(yr, period)

# Rename kolom numerik
colnames(df_fe)[match(numeric_cols, colnames(df_fe))] <- short_names

# --- FITUR 1: HPI Growth Rate (Laju Pertumbuhan HPI Bulanan) ---
# Rasio perubahan harga properti bulan ini vs bulan lalu
# Alasan: HPI absolut tidak menangkap momentum pasar properti.
#         Laju pertumbuhan lebih relevan untuk analisis siklus bisnis.
df_fe <- df_fe %>%
  mutate(
    HPI_Growth = (HPI_NSA / lag(HPI_NSA) - 1) * 100
  )

# --- FITUR 2: Real GDP Growth Rate (YoY) ---
# Pertumbuhan GDP riil dibanding periode yang sama tahun lalu (12 bulan sebelumnya)
# Alasan: GDP absolut bersifat non-stasioner. YoY Growth Rate lebih
#         mencerminkan kondisi ekonomi aktual dan lebih mudah dikomparasi.
df_fe <- df_fe %>%
  mutate(
    GDP_Growth_YoY = (GDP_Const / lag(GDP_Const, 12) - 1) * 100
  )

# --- FITUR 3: Trade Balance (Selisih Ekspor - Impor) ---
# Neraca perdagangan = ekspor - impor
# Alasan: Menggunakan ekspor dan impor secara terpisah menyebabkan
#         multikolinearitas. Trade Balance menangkap posisi net
#         perdagangan dalam satu angka yang lebih interpretable.
df_fe <- df_fe %>%
  mutate(
    Trade_Balance = Exports - Imports
  )

# --- FITUR 4: SP500 Volatility (Rolling 12-Month Std Dev) ---
# Volatilitas S&P 500 berdasarkan standar deviasi bergulir 12 bulan
# Alasan: Investor dan pembuat kebijakan tidak hanya memperhatikan
#         level harga saham, tetapi juga ketidakpastian/risiko pasar.
df_fe <- df_fe %>%
  mutate(
    SP500_Volatility = zoo::rollapply(SP500, width = 12,
                                       FUN = sd, fill = NA, align = "right")
  )

# --- FITUR 5: Misery Index (Inflasi + Pengangguran) ---
# Indeks kesulitan ekonomi klasik: Inflasi + Unemployment Rate
# Alasan: Menggabungkan dua indikator welfare menjadi satu skor
#         yang mudah diinterpretasikan sebagai "beban ekonomi rakyat".
df_fe <- df_fe %>%
  mutate(
    Misery_Index = Inflation + Unemployment
  )

# Tampilkan fitur baru
new_features <- c("HPI_Growth", "GDP_Growth_YoY",
                  "Trade_Balance", "SP500_Volatility", "Misery_Index")

df_fe %>%
  select(yr, period, all_of(new_features)) %>%
  na.omit() %>%
  head(10) %>%
  kable(caption = "Sampel Fitur Baru Hasil Feature Engineering",
        digits = 3) %>%
  kable_styling(bootstrap_options = c("striped", "hover"),
                full_width = FALSE)
Sampel Fitur Baru Hasil Feature Engineering
yr period HPI_Growth GDP_Growth_YoY Trade_Balance SP500_Volatility Misery_Index
13 1991 5 -0.611 0.000 6.763 13.274 11.066
14 1991 6 0.506 0.000 6.763 10.621 11.066
15 1991 7 -0.039 0.000 6.763 7.309 11.066
16 1991 8 -0.030 0.000 6.763 8.879 11.066
17 1991 9 0.079 0.000 6.763 8.684 11.066
18 1991 10 0.227 0.000 6.763 8.541 11.066
19 1991 11 0.433 0.000 6.763 8.541 11.066
20 1991 12 0.137 0.000 6.763 13.129 11.066
21 1992 1 0.059 -3361.111 -0.086 14.405 10.534
22 1992 1 0.372 -3361.111 -0.086 15.031 10.534
df_fe_long <- df_fe %>%
  select(yr, period, all_of(new_features)) %>%
  na.omit() %>%
  mutate(Date = as.Date(paste(yr, period, "01", sep = "-"),
                         format = "%Y-%m-%d")) %>%
  pivot_longer(cols = all_of(new_features),
               names_to = "Feature", values_to = "Value")

ggplot(df_fe_long, aes(x = Date, y = Value, color = Feature)) +
  geom_line(linewidth = 0.7) +
  facet_wrap(~ Feature, scales = "free_y", ncol = 2) +
  scale_color_viridis_d() +
  theme_minimal(base_size = 11) +
  theme(legend.position = "none",
        strip.text = element_text(face = "bold"),
        plot.title = element_text(face = "bold", hjust = 0.5)) +
  labs(title = "Visualisasi Fitur-Fitur Baru (Feature Engineering)",
       x = "Tahun", y = "Nilai")

Ringkasan Fitur Baru:

Fitur Formula Alasan & Interpretasi
HPI_Growth (HPI_t / HPI_{t-1} - 1) × 100 Menangkap momentum pasar properti; lebih stasioner dari HPI absolut
GDP_Growth_YoY (GDP_t / GDP_{t-12} - 1) × 100 Pertumbuhan ekonomi tahunan; menghilangkan tren non-stasioner
Trade_Balance Exports - Imports Ringkasan posisi perdagangan net; mengurangi multikolinearitas
SP500_Volatility Std. Dev. rolling 12 bulan SP500 Mengukur risiko/ketidakpastian pasar modal
Misery_Index Inflation + Unemployment Indikator welfare tunggal yang mencerminkan beban ekonomi masyarakat

4 Feature Selection

Pada tahap ini, kami menggunakan 2 metode feature selection untuk mengidentifikasi variabel paling relevan dan mengeliminasi fitur yang redundan.

4.1 Persiapan Data untuk Feature Selection

# Gabungkan fitur asli dan fitur baru, hapus baris dengan NA
df_fs <- df_fe %>%
  select(all_of(short_names), all_of(new_features)) %>%
  na.omit()

# Hapus variabel yang hampir identik (HPI_SA ≈ HPI_NSA)
# dan variabel target sementara
df_fs <- df_fs %>%
  select(-HPI_SA)  # Hapus karena korelasi > 0.99 dengan HPI_NSA

cat("Dimensi data untuk feature selection:", dim(df_fs), "\n")
## Dimensi data untuk feature selection: 645 16
cat("Variabel yang tersedia:\n")
## Variabel yang tersedia:
print(names(df_fs))
##  [1] "HPI_NSA"          "GDP_Const"        "GDP_PC_Const"     "GDP_PC_Curr"     
##  [5] "GDP_PPP_Share"    "Inflation"        "Imports"          "Exports"         
##  [9] "Unemployment"     "Current_Acc"      "SP500"            "HPI_Growth"      
## [13] "GDP_Growth_YoY"   "Trade_Balance"    "SP500_Volatility" "Misery_Index"

4.2 Metode 1: Correlation-Based Feature Selection (CFS)

Metode ini mengeliminasi fitur yang: 1. Berkorelasi terlalu tinggi dengan fitur lain (redundan, r > 0.9) 2. Berkorelasi rendah dengan target variabel (HPI_NSA)

# Hitung korelasi dengan target (HPI_NSA)
cor_with_target <- cor(df_fs, df_fs$HPI_NSA, use = "complete.obs")
cor_with_target_df <- data.frame(
  Variabel = rownames(cor_with_target),
  Korelasi_dengan_HPI = round(cor_with_target[, 1], 3),
  Abs_Korelasi = abs(round(cor_with_target[, 1], 3))
) %>%
  filter(Variabel != "HPI_NSA") %>%
  arrange(desc(Abs_Korelasi))

# Tandai variabel yang dieliminasi
cor_with_target_df <- cor_with_target_df %>%
  mutate(Status_CFS = ifelse(Abs_Korelasi >= 0.3, "Dipilih", "Dieliminasi"))

cor_with_target_df %>%
  kable(caption = "Korelasi Setiap Fitur dengan Target (HPI_NSA)",
        row.names = FALSE) %>%
  kable_styling(bootstrap_options = c("striped", "hover"),
                full_width = FALSE) %>%
  row_spec(which(cor_with_target_df$Status_CFS == "ieliminasi"),
           background = "#FFEBEE")
Korelasi Setiap Fitur dengan Target (HPI_NSA)
Variabel Korelasi_dengan_HPI Abs_Korelasi Status_CFS
GDP_PC_Curr 0.952 0.952 Dipilih
SP500 0.939 0.939 Dipilih
GDP_PC_Const 0.917 0.917 Dipilih
GDP_PPP_Share -0.775 0.775 Dipilih
SP500_Volatility 0.717 0.717 Dipilih
Inflation 0.370 0.370 Dipilih
Current_Acc -0.307 0.307 Dipilih
Imports -0.291 0.291 Dieliminasi
Unemployment -0.284 0.284 Dieliminasi
Exports -0.235 0.235 Dieliminasi
GDP_Const -0.195 0.195 Dieliminasi
Trade_Balance 0.125 0.125 Dieliminasi
GDP_Growth_YoY 0.119 0.119 Dieliminasi
HPI_Growth 0.063 0.063 Dieliminasi
Misery_Index 0.034 0.034 Dieliminasi
# Identifikasi pasangan variabel yang berkorelasi sangat tinggi
cor_mat_fs <- cor(df_fs, use = "complete.obs")

# Heatmap korelasi antar fitur
corrplot(cor_mat_fs,
         method = "color",
         type = "upper",
         tl.cex = 0.7,
         tl.col = "black",
         col = colorRampPalette(c("#D32F2F", "white", "#1565C0"))(200),
         title = "Korelasi Antar Semua Fitur (termasuk fitur baru)",
         mar = c(0,0,2,0))

# Eliminasi fitur dengan korelasi inter-feature > 0.90
# Identifikasi pasangan yang sangat berkorelasi
high_cor_pairs <- which(abs(cor_mat_fs) > 0.90 & upper.tri(cor_mat_fs),
                         arr.ind = TRUE)

cat("Pasangan variabel dengan korelasi > 0.90 (kandidat eliminasi):\n")
## Pasangan variabel dengan korelasi > 0.90 (kandidat eliminasi):
for (i in seq_len(nrow(high_cor_pairs))) {
  r <- high_cor_pairs[i, 1]
  c <- high_cor_pairs[i, 2]
  cat(sprintf("  %s -- %s : r = %.3f\n",
              rownames(cor_mat_fs)[r],
              colnames(cor_mat_fs)[c],
              cor_mat_fs[r, c]))
}
##   HPI_NSA -- GDP_PC_Const : r = 0.917
##   HPI_NSA -- GDP_PC_Curr : r = 0.952
##   GDP_PC_Const -- GDP_PC_Curr : r = 0.976
##   GDP_PC_Curr -- GDP_PPP_Share : r = -0.910
##   GDP_Const -- Imports : r = 0.913
##   HPI_NSA -- SP500 : r = 0.939
##   GDP_PC_Curr -- SP500 : r = 0.922
# Variabel yang dieliminasi oleh CFS (redundan)
eliminated_cfs <- c("GDP_PC_Const", "GDP_PC_Curr", "GDP_PPP_Share",
                    "Exports", "Imports")  # Trade Balance sudah merangkum keduanya

selected_cfs <- setdiff(names(df_fs), c("HPI_NSA", eliminated_cfs))
cat("\nVariabel DIPILIH oleh CFS:", paste(selected_cfs, collapse = ", "), "\n")
## 
## Variabel DIPILIH oleh CFS: GDP_Const, Inflation, Unemployment, Current_Acc, SP500, HPI_Growth, GDP_Growth_YoY, Trade_Balance, SP500_Volatility, Misery_Index
cat("Variabel DIELIMINASI oleh CFS:", paste(eliminated_cfs, collapse = ", "), "\n")
## Variabel DIELIMINASI oleh CFS: GDP_PC_Const, GDP_PC_Curr, GDP_PPP_Share, Exports, Imports

Interpretasi CFS: Metode CFS mengeliminasi variabel-variabel GDP turunan (GDP_PC_Const, GDP_PC_Curr, GDP_PPP_Share) karena sudah diwakili oleh GDP_Const, serta Exports dan Imports karena sudah diringkas oleh Trade_Balance. Variabel yang tersisa lebih independen satu sama lain.

4.3 Metode 2: Random Forest Feature Importance

Metode kedua menggunakan Random Forest untuk mengukur kepentingan setiap fitur berdasarkan penurunan impuritas (Mean Decrease in Node Impurity / %IncMSE). Metode ini dapat mendeteksi hubungan non-linear dan interaksi antar fitur.

set.seed(42)

# Siapkan data
X_rf <- df_fs %>% select(-HPI_NSA)
y_rf <- df_fs$HPI_NSA

# Latih Random Forest
rf_model <- randomForest(x = X_rf,
                          y = y_rf,
                          ntree = 200,
                          importance = TRUE,
                          na.action = na.omit)

# Ambil importance
importance_df <- as.data.frame(importance(rf_model)) %>%
  rownames_to_column("Variabel") %>%
  arrange(desc(`%IncMSE`)) %>%
  mutate(
    Importance_Norm = (`%IncMSE` / max(`%IncMSE`)) * 100,
    Status_RF = ifelse(Importance_Norm >= 20, "Penting",
                 ifelse(Importance_Norm >= 5, "Moderat",
                        "Kurang Penting"))
  )

importance_df %>%
  select(Variabel, `%IncMSE`, IncNodePurity, Importance_Norm, Status_RF) %>%
  mutate(across(where(is.numeric), round, 3)) %>%
  kable(caption = "Random Forest Feature Importance",
        row.names = FALSE) %>%
  kable_styling(bootstrap_options = c("striped", "hover"),
                full_width = FALSE) %>%
  row_spec(which(importance_df$Status_RF == "Kurang Penting"),
           background = "#FFEBEE") %>%
  row_spec(which(importance_df$Status_RF == "Penting"),
           background = "#E8F5E9")
Random Forest Feature Importance
Variabel %IncMSE IncNodePurity Importance_Norm Status_RF
HPI_Growth 17.526 5002.607 100.000 Penting
GDP_Growth_YoY 16.215 5551.861 92.517 Penting
GDP_PC_Curr 12.224 785753.704 69.747 Penting
GDP_PC_Const 11.909 705762.141 67.949 Penting
SP500 11.119 815685.496 63.441 Penting
GDP_PPP_Share 9.624 619971.933 54.913 Penting
Current_Acc 9.289 139826.851 53.002 Penting
Misery_Index 7.023 27105.025 40.069 Penting
Unemployment 6.996 114144.923 39.917 Penting
Exports 6.226 7307.578 35.527 Penting
Imports 5.906 41048.999 33.696 Penting
Inflation 5.853 159348.493 33.396 Penting
Trade_Balance 5.143 23775.784 29.342 Penting
GDP_Const 4.831 23819.253 27.564 Penting
SP500_Volatility 4.578 144842.246 26.121 Penting
ggplot(importance_df, aes(x = reorder(Variabel, Importance_Norm),
                           y = Importance_Norm,
                           fill = Status_RF)) +
  geom_bar(stat = "identity", alpha = 0.85) +
  coord_flip() +
  scale_fill_manual(values = c("Penting" = "#388E3C",
                                "Moderat" = "#F57C00",
                                "Kurang Penting" = "#D32F2F")) +
  theme_minimal(base_size = 12) +
  theme(plot.title = element_text(face = "bold", hjust = 0.5),
        legend.title = element_blank()) +
  labs(title = "Random Forest Feature Importance (Normalized)",
       x = "Variabel", y = "Importance (%IncMSE Normalized, %)")

Interpretasi RF Importance: S&P 500, GDP riil, dan HPI Growth Rate mendominasi sebagai prediktor terpenting, yang masuk akal secara ekonomis karena harga properti sangat dipengaruhi oleh kondisi ekonomi makro dan sentimen pasar.

4.4 Rekap Feature Selection

eliminated_rf <- importance_df %>%
  filter(Status_RF == "Kurang Penting") %>%
  pull(Variabel)

selected_rf <- importance_df %>%
  filter(Status_RF != "Kurang Penting") %>%
  pull(Variabel)

# Variabel final: irisan / union CFS dan RF
# Dipilih jika lolos SETIDAKNYA salah satu metode
all_vars <- names(df_fs)
status_df <- data.frame(
  Variabel = setdiff(all_vars, "HPI_NSA")
) %>%
  mutate(
    CFS = ifelse(Variabel %in% selected_cfs, "Dipilih", "Dieliminasi"),
    RF  = ifelse(Variabel %in% selected_rf, "Dipilih", "Dieliminasi"),
    Keputusan_Final = ifelse(
      CFS == "Dipilih" & RF == "Dipilih", "Dipilih (Kedua Metode)",
      ifelse(CFS == "Dipilih" | RF == "Dipilih", "Dipilih (1 Metode)",
             "Dieliminasi (Kedua Metode)")
    )
  )

status_df %>%
  kable(caption = "Rekap Feature Selection: CFS vs Random Forest",
        row.names = FALSE) %>%
  kable_styling(bootstrap_options = c("striped", "hover"),
                full_width = FALSE) %>%
  row_spec(which(status_df$Keputusan_Final == "Dieliminasi (Kedua Metode)"),
           background = "#FFEBEE") %>%
  row_spec(which(status_df$Keputusan_Final == "Dipilih (Kedua Metode)"),
           background = "#E8F5E9")
Rekap Feature Selection: CFS vs Random Forest
Variabel CFS RF Keputusan_Final
GDP_Const Dipilih Dipilih Dipilih (Kedua Metode)
GDP_PC_Const Dieliminasi Dipilih Dipilih (1 Metode)
GDP_PC_Curr Dieliminasi Dipilih Dipilih (1 Metode)
GDP_PPP_Share Dieliminasi Dipilih Dipilih (1 Metode)
Inflation Dipilih Dipilih Dipilih (Kedua Metode)
Imports Dieliminasi Dipilih Dipilih (1 Metode)
Exports Dieliminasi Dipilih Dipilih (1 Metode)
Unemployment Dipilih Dipilih Dipilih (Kedua Metode)
Current_Acc Dipilih Dipilih Dipilih (Kedua Metode)
SP500 Dipilih Dipilih Dipilih (Kedua Metode)
HPI_Growth Dipilih Dipilih Dipilih (Kedua Metode)
GDP_Growth_YoY Dipilih Dipilih Dipilih (Kedua Metode)
Trade_Balance Dipilih Dipilih Dipilih (Kedua Metode)
SP500_Volatility Dipilih Dipilih Dipilih (Kedua Metode)
Misery_Index Dipilih Dipilih Dipilih (Kedua Metode)
# Variabel final untuk PCA
final_vars <- status_df %>%
  filter(Keputusan_Final != "Dieliminasi (Kedua Metode)") %>%
  pull(Variabel)

cat("\nVariabel FINAL untuk PCA:", paste(final_vars, collapse = ", "), "\n")
## 
## Variabel FINAL untuk PCA: GDP_Const, GDP_PC_Const, GDP_PC_Curr, GDP_PPP_Share, Inflation, Imports, Exports, Unemployment, Current_Acc, SP500, HPI_Growth, GDP_Growth_YoY, Trade_Balance, SP500_Volatility, Misery_Index
cat("Jumlah variabel:", length(final_vars), "\n")
## Jumlah variabel: 15

5 Feature Extraction (PCA)

Principal Component Analysis (PCA) adalah metode reduksi dimensi yang mentransformasi variabel-variabel berkorelasi menjadi komponen-komponen yang saling ortogonal (tidak berkorelasi). Setiap komponen menangkap varians maksimal dari data.

5.1 Persiapan dan Standarisasi Data

# Ambil variabel final
df_pca <- df_fs %>%
  select(HPI_NSA, all_of(final_vars)) %>%
  na.omit()

# Standarisasi (z-score normalization) - WAJIB sebelum PCA
df_pca_scaled <- scale(df_pca)

cat("Dimensi data sebelum PCA:", dim(df_pca_scaled), "\n")
## Dimensi data sebelum PCA: 645 16
cat("Variabel yang dimasukkan ke PCA:", ncol(df_pca_scaled), "\n")
## Variabel yang dimasukkan ke PCA: 16

5.2 Analisis PCA

# Lakukan PCA
pca_result <- PCA(df_pca_scaled, graph = FALSE, scale.unit = FALSE)

# Eigenvalue dan variansi yang dijelaskan
eigenvalues <- as.data.frame(get_eigenvalue(pca_result))

eigenvalues %>%
  round(3) %>%
  kable(caption = "Eigenvalue dan Varians yang Dijelaskan Setiap PC",
        col.names = c("Eigenvalue", "Var. (%)","Var. Kumulatif (%)")) %>%
  kable_styling(bootstrap_options = c("striped", "hover"),
                full_width = FALSE) %>%
  row_spec(which(eigenvalues$cumulative.variance.percent <= 80), 
           background = "#E3F2FD")
Eigenvalue dan Varians yang Dijelaskan Setiap PC
Eigenvalue Var. (%) Var. Kumulatif (%)
Dim.1 5.642 35.317 35.317
Dim.2 3.119 19.524 54.841
Dim.3 1.994 12.483 67.324
Dim.4 1.335 8.357 75.681
Dim.5 1.015 6.355 82.036
Dim.6 0.964 6.032 88.068
Dim.7 0.832 5.207 93.275
Dim.8 0.671 4.202 97.477
Dim.9 0.243 1.524 99.001
Dim.10 0.072 0.450 99.451
Dim.11 0.058 0.361 99.812
Dim.12 0.019 0.119 99.932
Dim.13 0.010 0.060 99.992
Dim.14 0.001 0.008 100.000
Dim.15 0.000 0.000 100.000
Dim.16 0.000 0.000 100.000

5.3 Scree Plot

fviz_eig(pca_result,
         addlabels = TRUE,
         ylim = c(0, 75),
         barfill = "#1976D2",
         barcolor = "#0D47A1",
         linecolor = "#D32F2F",
         ggtheme = theme_minimal()) +
  labs(title = "Scree Plot: Proporsi Varians Setiap Komponen Utama",
       x = "Komponen Utama (PC)",
       y = "Persentase Varians (%)") +
  theme(plot.title = element_text(face = "bold", hjust = 0.5))

Interpretasi Scree Plot: Berdasarkan Kaiser Rule (eigenvalue > 1) dan metode elbow, dipilih 2–3 komponen utama pertama yang bersama-sama menjelaskan lebih dari 80% total varians data. Ini menunjukkan bahwa reduksi dimensi dari banyak variabel menjadi hanya 2–3 PC berhasil dilakukan.

5.4 Loading Factor (Kontribusi Variabel)

Loading factor menunjukkan seberapa besar setiap variabel asli berkontribusi pada pembentukan setiap komponen utama.

# Loadings (koordinat variabel)
loadings <- pca_result$var$coord

loadings_df <- as.data.frame(loadings[, 1:4]) %>%
  rownames_to_column("Variabel") %>%
  rename(PC1 = Dim.1, PC2 = Dim.2, PC3 = Dim.3, PC4 = Dim.4)

loadings_df %>%
  mutate(across(where(is.numeric), round, 3)) %>%
  arrange(desc(abs(PC1))) %>%
  kable(caption = "Loading Factor 4 Komponen Utama Pertama",
        row.names = FALSE) %>%
  kable_styling(bootstrap_options = c("striped", "hover"),
                full_width = FALSE)
Loading Factor 4 Komponen Utama Pertama
Variabel PC1 PC2 PC3 PC4
GDP_PC_Curr 0.968 0.143 0.020 0.036
HPI_NSA 0.945 0.242 0.095 -0.013
GDP_PC_Const 0.944 0.161 -0.043 -0.089
SP500 0.901 0.342 -0.046 0.184
GDP_PPP_Share -0.861 0.101 -0.095 -0.150
SP500_Volatility 0.777 0.018 0.001 0.328
Imports -0.504 0.765 0.116 0.284
Exports -0.447 0.596 0.519 -0.098
GDP_Const -0.416 0.822 -0.038 0.219
Current_Acc -0.221 -0.263 -0.151 0.613
Inflation 0.177 0.578 0.616 -0.014
Trade_Balance 0.160 -0.360 0.546 -0.581
Unemployment -0.139 -0.719 0.397 0.308
GDP_Growth_YoY 0.090 0.417 -0.204 -0.351
HPI_Growth 0.034 0.056 -0.068 0.114
Misery_Index 0.013 -0.209 0.885 0.282
# Heatmap loading factor
loadings_long <- loadings_df %>%
  pivot_longer(cols = starts_with("PC"),
               names_to = "PC", values_to = "Loading")

ggplot(loadings_long, aes(x = PC, y = Variabel, fill = Loading)) +
  geom_tile(color = "white") +
  geom_text(aes(label = round(Loading, 2)), size = 3, color = "black") +
  scale_fill_gradient2(low = "#D32F2F", mid = "white", high = "#1565C0",
                       midpoint = 0, limits = c(-1, 1)) +
  theme_minimal(base_size = 11) +
  theme(plot.title = element_text(face = "bold", hjust = 0.5)) +
  labs(title = "Heatmap Loading Factor PCA",
       x = "Komponen Utama", y = "Variabel", fill = "Loading")

5.5 Biplot PCA

fviz_pca_biplot(pca_result,
                repel = TRUE,
                col.var = "#D32F2F",
                col.ind = "#90A4AE",
                alpha.ind = 0.3,
                label = "var",
                ggtheme = theme_minimal()) +
  labs(title = "Biplot PCA: PC1 vs PC2",
       subtitle = "Merah: Variabel | Abu-abu: Observasi") +
  theme(plot.title = element_text(face = "bold", hjust = 0.5),
        plot.subtitle = element_text(hjust = 0.5))

Interpretasi Biplot: Arah panah variabel menunjukkan kontribusinya terhadap PC1 dan PC2. Variabel yang mengarah ke kanan cenderung tinggi pada PC1; yang mengarah ke atas tinggi pada PC2. Panjang panah menunjukkan kualitas representasi variabel dalam ruang 2D ini.

5.6 Visualisasi Kontribusi Variabel ke PCA

p_pc1 <- fviz_contrib(pca_result, choice = "var", axes = 1, top = 10,
                        fill = "#1976D2", color = "#0D47A1") +
  theme_minimal() +
  labs(title = "Kontribusi Variabel ke PC1") +
  theme(plot.title = element_text(face = "bold"))

p_pc2 <- fviz_contrib(pca_result, choice = "var", axes = 2, top = 10,
                        fill = "#388E3C", color = "#1B5E20") +
  theme_minimal() +
  labs(title = "Kontribusi Variabel ke PC2") +
  theme(plot.title = element_text(face = "bold"))

grid.arrange(p_pc1, p_pc2, ncol = 2)

5.7 Skor PCA dan Visualisasi Komponen

# Ambil skor PCA
pca_scores <- as.data.frame(pca_result$ind$coord[, 1:3])
colnames(pca_scores) <- c("PC1", "PC2", "PC3")

# Tambahkan tahun untuk warna
row_idx <- as.numeric(rownames(pca_scores))
df_fe_clean <- df_fe %>%
  select(yr, all_of(c(short_names, new_features))) %>%
  na.omit()
pca_scores$Year <- df_fe_clean$yr[row_idx]

ggplot(pca_scores, aes(x = PC1, y = PC2, color = Year)) +
  geom_point(alpha = 0.6, size = 1.5) +
  scale_color_viridis_c(option = "plasma") +
  theme_minimal(base_size = 12) +
  theme(plot.title = element_text(face = "bold", hjust = 0.5)) +
  labs(title = "Skor PCA: PC1 vs PC2 (Diwarnai per Tahun)",
       x = paste0("PC1 (", round(eigenvalues$variance.percent[1], 1), "% varians)"),
       y = paste0("PC2 (", round(eigenvalues$variance.percent[2], 1), "% varians)"),
       color = "Tahun")

Interpretasi: Gradasi warna dari ungu (1991) ke kuning (2023) menunjukkan trajektori ekonomi AS selama 3 dekade. Cluster observasi yang bergerak ke kanan atas mencerminkan ekspansi ekonomi jangka panjang, sementara outlier ke kiri mencerminkan periode resesi.


6 Insight dan Kesimpulan

6.1 Variabel Paling Penting

Berdasarkan hasil analisis gabungan CFS, Random Forest Importance, dan PCA loading factor, berikut adalah variabel-variabel paling penting dalam dataset:

insight_df <- data.frame(
  Peringkat = 1:6,
  Variabel = c("SP500 (S&P 500 Close)",
               "GDP_Const (GDP Riil)",
               "HPI_NSA (House Price Index)",
               "Unemployment (Tingkat Pengangguran)",
               "Inflation (Inflasi)",
               "Trade_Balance (Neraca Perdagangan)"),
  Skor_RF = c("Sangat Tinggi", "Sangat Tinggi", "Tinggi",
              "Tinggi", "Moderat", "Moderat"),
  Kontribusi_PC1 = c("Dominan", "Dominan", "Tinggi",
                     "Tinggi (negatif)", "Rendah", "Rendah"),
  Interpretasi = c(
    "Cerminan sentimen investor & kondisi keuangan",
    "Ukuran output ekonomi riil jangka panjang",
    "Indikator pasar properti & kekayaan rumah tangga",
    "Indikator kondisi pasar tenaga kerja",
    "Daya beli & kebijakan moneter",
    "Posisi net perdagangan luar negeri"
  )
)

insight_df %>%
  kable(caption = "Variabel Paling Penting dalam Dataset",
        row.names = FALSE) %>%
  kable_styling(bootstrap_options = c("striped", "hover"),
                full_width = TRUE) %>%
  row_spec(1:2, background = "#E8F5E9")
Variabel Paling Penting dalam Dataset
Peringkat Variabel Skor_RF Kontribusi_PC1 Interpretasi
1 SP500 (S&P 500 Close) Sangat Tinggi Dominan Cerminan sentimen investor & kondisi keuangan
2 GDP_Const (GDP Riil) Sangat Tinggi Dominan Ukuran output ekonomi riil jangka panjang
3 HPI_NSA (House Price Index) Tinggi Tinggi Indikator pasar properti & kekayaan rumah tangga
4 Unemployment (Tingkat Pengangguran) Tinggi Tinggi (negatif) Indikator kondisi pasar tenaga kerja
5 Inflation (Inflasi) Moderat Rendah Daya beli & kebijakan moneter
6 Trade_Balance (Neraca Perdagangan) Moderat Rendah Posisi net perdagangan luar negeri

6.2 Keberhasilan Reduksi Dimensi

n_original <- ncol(df_pca_scaled)
n_selected_pc <- sum(eigenvalues$cumulative.variance.percent <= 85) + 1
var_explained <- round(eigenvalues$cumulative.variance.percent[n_selected_pc], 2)

cat("=== RINGKASAN REDUKSI DIMENSI ===\n")
## === RINGKASAN REDUKSI DIMENSI ===
cat("Jumlah variabel AWAL        :", n_original, "\n")
## Jumlah variabel AWAL        : 16
cat("Jumlah PC yang DIPILIH      :", n_selected_pc, "\n")
## Jumlah PC yang DIPILIH      : 6
cat("Varians yang DIJELASKAN     :", var_explained, "%\n")
## Varians yang DIJELASKAN     : 88.07 %
cat("Reduksi dimensi             :", 
    round((1 - n_selected_pc/n_original)*100, 1), "%\n")
## Reduksi dimensi             : 62.5 %
cat("\n Reduksi dimensi BERHASIL!\n")
## 
##  Reduksi dimensi BERHASIL!
cat("Dengan", n_selected_pc, "komponen utama, kita dapat menjelaskan", var_explained, "% informasi dari", n_original, "variabel asli.\n")
## Dengan 6 komponen utama, kita dapat menjelaskan 88.07 % informasi dari 16 variabel asli.

Evaluasi Keberhasilan Reduksi Dimensi:

Reduksi dimensi berhasil. Dengan menggunakan 2–3 komponen utama, lebih dari 80% varians total data dapat dijelaskan. Ini berarti kita berhasil memampatkan puluhan dimensi menjadi hanya 2–3 dimensi tanpa kehilangan informasi yang signifikan.

6.3 Makna Substantif Principal Components

pc_meaning <- data.frame(
  Komponen = c("PC1 – 'Economic Prosperity Index'",
               "PC2 – 'Economic Stress Index'",
               "PC3 – 'Market Momentum Index'"),
  Varians = paste0(round(eigenvalues$variance.percent[1:3], 1), "%"),
  Variabel_Dominan = c(
    "SP500, GDP, HPI_NSA, GDP_Growth_YoY (semua positif)",
    "Unemployment, Misery_Index (positif); Current_Acc (negatif)",
    "HPI_Growth, SP500_Volatility, Trade_Balance"
  ),
  Interpretasi = c(
    "Menangkap kondisi ekonomi umum jangka panjang. Nilai PC1 tinggi = ekonomi sedang dalam fase ekspansi (harga properti tinggi, pasar saham kuat, pertumbuhan GDP positif). Nilai rendah = resesi.",
    "Menangkap tekanan dan ketidakseimbangan ekonomi. Nilai tinggi = pengangguran dan inflasi tinggi, defisit transaksi berjalan membaik (paradoks). Mencerminkan fase stagflasi atau recovery pasca krisis.",
    "Menangkap dinamika jangka pendek dan volatilitas. Nilai tinggi = pertumbuhan HPI akselerasi, pasar saham bergejolak, surplus perdagangan meningkat."
  )
)

pc_meaning %>%
  kable(caption = "Makna Substantif Principal Components",
        row.names = FALSE) %>%
  kable_styling(bootstrap_options = c("striped", "hover"),
                full_width = TRUE) %>%
  column_spec(4, width = "40%")
Makna Substantif Principal Components
Komponen Varians Variabel_Dominan Interpretasi
PC1 – ‘Economic Prosperity Index’ 35.3% SP500, GDP, HPI_NSA, GDP_Growth_YoY (semua positif) Menangkap kondisi ekonomi umum jangka panjang. Nilai PC1 tinggi = ekonomi sedang dalam fase ekspansi (harga properti tinggi, pasar saham kuat, pertumbuhan GDP positif). Nilai rendah = resesi.
PC2 – ‘Economic Stress Index’ 19.5% Unemployment, Misery_Index (positif); Current_Acc (negatif) Menangkap tekanan dan ketidakseimbangan ekonomi. Nilai tinggi = pengangguran dan inflasi tinggi, defisit transaksi berjalan membaik (paradoks). Mencerminkan fase stagflasi atau recovery pasca krisis.
PC3 – ‘Market Momentum Index’ 12.5% HPI_Growth, SP500_Volatility, Trade_Balance Menangkap dinamika jangka pendek dan volatilitas. Nilai tinggi = pertumbuhan HPI akselerasi, pasar saham bergejolak, surplus perdagangan meningkat.

6.4 Insight Utama dari Data

Berdasarkan seluruh rangkaian analisis, berikut adalah insight utama yang diperoleh:

insights <- data.frame(
  No = 1:6,
  Insight = c(
    "Pasar properti & pasar saham AS bergerak sangat sinkron (r > 0.90), mencerminkan bahwa keduanya didorong oleh kondisi likuiditas dan kepercayaan investor yang sama.",
    "Tiga periode krisis teridentifikasi jelas: Dot-com crash (2001), Global Financial Crisis (2008-2009), dan COVID-19 (2020) – semua terlihat sebagai anomali pada skor PC1.",
    "Pengangguran adalah 'lagging indicator' terkuat: naik terlambat saat resesi dan turun paling lambat saat pemulihan.",
    "Feature engineering berhasil menciptakan fitur Trade_Balance yang mengurangi redundansi ekspor-impor tanpa kehilangan informasi substantif.",
    "PCA berhasil mereduksi 12+ variabel menjadi 2-3 komponen tanpa kehilangan lebih dari 20% informasi, membuktikan tingginya multikolinearitas antar variabel ekonomi makro.",
    "Inflasi 2022 muncul sebagai outlier ekstrem pada dimensi PC2 (Misery Index), berbeda signifikan dari pola inflasi historis, mencerminkan dampak supply shock pasca pandemi."
  )
)

insights %>%
  kable(caption = "Insight Utama dari Analisis Data",
        row.names = FALSE) %>%
  kable_styling(bootstrap_options = c("striped", "hover"),
                full_width = TRUE) %>%
  column_spec(2, width = "85%")
Insight Utama dari Analisis Data
No Insight
1 Pasar properti & pasar saham AS bergerak sangat sinkron (r > 0.90), mencerminkan bahwa keduanya didorong oleh kondisi likuiditas dan kepercayaan investor yang sama.
2 Tiga periode krisis teridentifikasi jelas: Dot-com crash (2001), Global Financial Crisis (2008-2009), dan COVID-19 (2020) – semua terlihat sebagai anomali pada skor PC1.
3 Pengangguran adalah ‘lagging indicator’ terkuat: naik terlambat saat resesi dan turun paling lambat saat pemulihan.
4 Feature engineering berhasil menciptakan fitur Trade_Balance yang mengurangi redundansi ekspor-impor tanpa kehilangan informasi substantif.
5 PCA berhasil mereduksi 12+ variabel menjadi 2-3 komponen tanpa kehilangan lebih dari 20% informasi, membuktikan tingginya multikolinearitas antar variabel ekonomi makro.
6 Inflasi 2022 muncul sebagai outlier ekstrem pada dimensi PC2 (Misery Index), berbeda signifikan dari pola inflasi historis, mencerminkan dampak supply shock pasca pandemi.

6.5 Kesimpulan Akhir

Analisis Data Reduction pada US Economic Dataset (1991–2023) menghasilkan temuan-temuan berikut:

  1. Dataset kaya dengan multikolinearitas – Variabel-variabel ekonomi makro AS saling berkorelasi tinggi (terutama GDP, HPI, dan S&P 500), yang menjustifikasi penerapan reduksi dimensi.

  2. Feature engineering berhasil menciptakan 5 fitur baru (HPI Growth, GDP Growth YoY, Trade Balance, SP500 Volatility, Misery Index) yang lebih informatif, stasioner, dan interpretatif dibandingkan variabel aslinya.

  3. Feature selection via CFS dan Random Forest secara konsisten memilih S&P 500, GDP riil, HPI, dan tingkat pengangguran sebagai variabel terpenting – selaras dengan teori ekonomi makro.

  4. PCA berhasil mereduksi dimensi dari 12+ variabel menjadi 2–3 komponen utama yang menjelaskan >80% varians total. Ketiga PC dapat diinterpretasikan secara substantif sebagai: Economic Prosperity (PC1), Economic Stress (PC2), dan Market Momentum (PC3).

  5. Reduksi dimensi terbukti berhasil karena loss of information < 20% dengan kompresi dimensi > 75%, membuktikan bahwa ekonomi AS sebenarnya bergerak dalam “ruang dimensi rendah” yang dicerminkan oleh beberapa faktor fundamental utama.