=====================================================================
ANALISIS DATA PANEL MODEL LINIER - DATASET GRUNFELD (paket plm)
=====================================================================
0. PAKET
paket <- c("plm", "lmtest", "sandwich", "car", "stargazer")
for (p in paket) {
if (!requireNamespace(p, quietly = TRUE)) install.packages(p)
library(p, character.only = TRUE)
}
## Warning: package 'plm' was built under R version 4.5.3
## Loading required package: zoo
##
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
## Warning: package 'sandwich' was built under R version 4.5.2
## Warning: package 'car' was built under R version 4.5.2
## Loading required package: carData
## Warning: package 'carData' was built under R version 4.5.2
## Warning: package 'stargazer' was built under R version 4.5.2
##
## Please cite as:
## Hlavac, Marek (2022). stargazer: Well-Formatted Regression and Summary Statistics Tables.
## R package version 5.2.3. https://CRAN.R-project.org/package=stargazer
———————————————————————
1. DATA DAN STRUKTUR PANEL
———————————————————————
data("Grunfeld", package = "plm")
# inv = investasi, value = nilai pasar perusahaan, capital = stok modal
head(Grunfeld)
## firm year inv value capital
## 1 1 1935 317.6 3078.5 2.8
## 2 1 1936 391.8 4661.7 52.6
## 3 1 1937 410.6 5387.1 156.9
## 4 1 1938 257.7 2792.2 209.2
## 5 1 1939 330.8 4313.2 203.4
## 6 1 1940 461.2 4643.9 207.2
str(Grunfeld)
## 'data.frame': 200 obs. of 5 variables:
## $ firm : int 1 1 1 1 1 1 1 1 1 1 ...
## $ year : int 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 ...
## $ inv : num 318 392 411 258 331 ...
## $ value : num 3078 4662 5387 2792 4313 ...
## $ capital: num 2.8 52.6 156.9 209.2 203.4 ...
pdata <- pdata.frame(Grunfeld, index = c("firm", "year"))
pdim(pdata) # cek balanced / unbalanced, N, T, n
## Balanced Panel: n = 10, T = 20, N = 200
is.pbalanced(pdata)
## [1] TRUE
summary(pdata)
## firm year inv value
## 1 :20 1935 : 10 Min. : 0.93 Min. : 58.12
## 2 :20 1936 : 10 1st Qu.: 33.56 1st Qu.: 199.97
## 3 :20 1937 : 10 Median : 57.48 Median : 517.95
## 4 :20 1938 : 10 Mean : 145.96 Mean :1081.68
## 5 :20 1939 : 10 3rd Qu.: 138.04 3rd Qu.:1679.85
## 6 :20 1940 : 10 Max. :1486.70 Max. :6241.70
## (Other):80 (Other):140
## capital
## Min. : 0.80
## 1st Qu.: 79.17
## Median : 205.60
## Mean : 276.02
## 3rd Qu.: 358.10
## Max. :2226.30
##
———————————————————————
2. EKSPLORASI DATA
———————————————————————
# Statistik deskriptif
stargazer(Grunfeld[, c("inv", "value", "capital")], type = "text",
title = "Statistik Deskriptif", digits = 2)
##
## Statistik Deskriptif
## ==============================================
## Statistic N Mean St. Dev. Min Max
## ----------------------------------------------
## inv 200 145.96 216.88 0.93 1,486.70
## value 200 1,081.68 1,314.47 58.12 6,241.70
## capital 200 276.02 301.10 0.80 2,226.30
## ----------------------------------------------
# Korelasi antar variabel
cor(Grunfeld[, c("inv", "value", "capital")])
## inv value capital
## inv 1.0000000 0.8569329 0.6625653
## value 0.8569329 1.0000000 0.4887058
## capital 0.6625653 0.4887058 1.0000000
# Rata-rata per perusahaan dan per tahun
aggregate(inv ~ firm, data = Grunfeld, FUN = mean)
## firm inv
## 1 1 608.0200
## 2 2 410.4750
## 3 3 102.2900
## 4 4 86.1235
## 5 5 61.8025
## 6 6 55.4110
## 7 7 47.5955
## 8 8 42.8915
## 9 9 41.8890
## 10 10 3.0845
aggregate(inv ~ year, data = Grunfeld, FUN = mean)
## year inv
## 1 1935 72.746
## 2 1936 101.607
## 3 1937 122.481
## 4 1938 77.555
## 5 1939 80.526
## 6 1940 113.265
## 7 1941 139.719
## 8 1942 122.665
## 9 1943 117.790
## 10 1944 120.925
## 11 1945 124.159
## 12 1946 161.359
## 13 1947 147.135
## 14 1948 153.948
## 15 1949 139.244
## 16 1950 151.061
## 17 1951 199.583
## 18 1952 224.033
## 19 1953 275.583
## 20 1954 273.781
# Visualisasi
par(mfrow = c(1, 2))
boxplot(inv ~ firm, data = Grunfeld, main = "Investasi per Perusahaan",
xlab = "Firm", ylab = "inv")
plot(tapply(Grunfeld$inv, Grunfeld$year, mean), type = "b",
xaxt = "n", main = "Rata-rata Investasi per Tahun",
xlab = "Tahun", ylab = "inv")
axis(1, at = 1:20, labels = sort(unique(Grunfeld$year)))

par(mfrow = c(1, 1))
———————————————————————
3. ESTIMASI TIGA MODEL
———————————————————————
form <- inv ~ value + capital
cem <- plm(form, data = pdata, model = "pooling") # Common Effect
fem <- plm(form, data = pdata, model = "within") # Fixed Effect
rem <- plm(form, data = pdata, model = "random") # Random Effect
summary(cem)
## Pooling Model
##
## Call:
## plm(formula = form, data = pdata, model = "pooling")
##
## Balanced Panel: n = 10, T = 20, N = 200
##
## Residuals:
## Min. 1st Qu. Median 3rd Qu. Max.
## -291.6757 -30.0137 5.3033 34.8293 369.4464
##
## Coefficients:
## Estimate Std. Error t-value Pr(>|t|)
## (Intercept) -42.7143694 9.5116760 -4.4907 1.207e-05 ***
## value 0.1155622 0.0058357 19.8026 < 2.2e-16 ***
## capital 0.2306785 0.0254758 9.0548 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Total Sum of Squares: 9359900
## Residual Sum of Squares: 1755900
## R-Squared: 0.81241
## Adj. R-Squared: 0.8105
## F-statistic: 426.576 on 2 and 197 DF, p-value: < 2.22e-16
summary(fem)
## Oneway (individual) effect Within Model
##
## Call:
## plm(formula = form, data = pdata, model = "within")
##
## Balanced Panel: n = 10, T = 20, N = 200
##
## Residuals:
## Min. 1st Qu. Median 3rd Qu. Max.
## -184.00857 -17.64316 0.56337 19.19222 250.70974
##
## Coefficients:
## Estimate Std. Error t-value Pr(>|t|)
## value 0.110124 0.011857 9.2879 < 2.2e-16 ***
## capital 0.310065 0.017355 17.8666 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Total Sum of Squares: 2244400
## Residual Sum of Squares: 523480
## R-Squared: 0.76676
## Adj. R-Squared: 0.75311
## F-statistic: 309.014 on 2 and 188 DF, p-value: < 2.22e-16
summary(rem)
## Oneway (individual) effect Random Effect Model
## (Swamy-Arora's transformation)
##
## Call:
## plm(formula = form, data = pdata, model = "random")
##
## Balanced Panel: n = 10, T = 20, N = 200
##
## Effects:
## var std.dev share
## idiosyncratic 2784.46 52.77 0.282
## individual 7089.80 84.20 0.718
## theta: 0.8612
##
## Residuals:
## Min. 1st Qu. Median 3rd Qu. Max.
## -177.6063 -19.7350 4.6851 19.5105 252.8743
##
## Coefficients:
## Estimate Std. Error z-value Pr(>|z|)
## (Intercept) -57.834415 28.898935 -2.0013 0.04536 *
## value 0.109781 0.010493 10.4627 < 2e-16 ***
## capital 0.308113 0.017180 17.9339 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Total Sum of Squares: 2381400
## Residual Sum of Squares: 548900
## R-Squared: 0.7695
## Adj. R-Squared: 0.76716
## Chisq: 657.674 on 2 DF, p-value: < 2.22e-16
# Efek individu (intersep tiap perusahaan) pada FEM
fixef(fem)
## 1 2 3 4 5 6 7 8
## -70.2967 101.9058 -235.5718 -27.8093 -114.6168 -23.1613 -66.5535 -57.5457
## 9 10
## -87.2223 -6.5678
summary(fixef(fem))
## Estimate Std. Error t-value Pr(>|t|)
## 1 -70.2967 49.7080 -1.4142 0.15896
## 2 101.9058 24.9383 4.0863 6.485e-05 ***
## 3 -235.5718 24.4316 -9.6421 < 2.2e-16 ***
## 4 -27.8093 14.0778 -1.9754 0.04969 *
## 5 -114.6168 14.1654 -8.0913 7.141e-14 ***
## 6 -23.1613 12.6687 -1.8282 0.06910 .
## 7 -66.5535 12.8430 -5.1821 5.629e-07 ***
## 8 -57.5457 13.9931 -4.1124 5.848e-05 ***
## 9 -87.2223 12.8919 -6.7657 1.635e-10 ***
## 10 -6.5678 11.8269 -0.5553 0.57933
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# Komponen varians pada REM
ercomp(rem)
## var std.dev share
## idiosyncratic 2784.46 52.77 0.282
## individual 7089.80 84.20 0.718
## theta: 0.8612
# Perbandingan tabel
stargazer(cem, fem, rem, type = "text",
column.labels = c("CEM", "FEM", "REM"),
model.names = FALSE)
##
## =========================================================================
## Dependent variable:
## ------------------------------------------------------------
## inv
## CEM FEM REM
## (1) (2) (3)
## -------------------------------------------------------------------------
## value 0.116*** 0.110*** 0.110***
## (0.006) (0.012) (0.010)
##
## capital 0.231*** 0.310*** 0.308***
## (0.025) (0.017) (0.017)
##
## Constant -42.714*** -57.834**
## (9.512) (28.899)
##
## -------------------------------------------------------------------------
## Observations 200 200 200
## R2 0.812 0.767 0.770
## Adjusted R2 0.811 0.753 0.767
## F Statistic 426.576*** (df = 2; 197) 309.014*** (df = 2; 188) 657.674***
## =========================================================================
## Note: *p<0.1; **p<0.05; ***p<0.01
———————————————————————
4. UJI PEMILIHAN MODEL
———————————————————————
chow <- pFtest(fem, cem) # CEM vs FEM
bp_lm <- plmtest(cem, type = "bp") # CEM vs REM
hausman <- phtest(fem, rem) # FEM vs REM
print(chow)
##
## F test for individual effects
##
## data: form
## F = 49.177, df1 = 9, df2 = 188, p-value < 2.2e-16
## alternative hypothesis: significant effects
print(bp_lm)
##
## Lagrange Multiplier Test - (Breusch-Pagan)
##
## data: form
## chisq = 798.16, df = 1, p-value < 2.2e-16
## alternative hypothesis: significant effects
print(hausman)
##
## Hausman Test
##
## data: form
## chisq = 2.3304, df = 2, p-value = 0.3119
## alternative hypothesis: one model is inconsistent
# Kesimpulan otomatis (alpha = 5%)
alpha <- 0.05
cat("\n===== KESIMPULAN UJI PEMILIHAN MODEL =====\n")
##
## ===== KESIMPULAN UJI PEMILIHAN MODEL =====
cat("Uji Chow : p =", signif(chow$p.value, 4), "->",
ifelse(chow$p.value < alpha, "FEM lebih baik dari CEM", "CEM cukup"), "\n")
## Uji Chow : p = 8.7e-45 -> FEM lebih baik dari CEM
cat("Uji BP-LM : p =", signif(bp_lm$p.value, 4), "->",
ifelse(bp_lm$p.value < alpha, "REM lebih baik dari CEM", "CEM cukup"), "\n")
## Uji BP-LM : p = 1.354e-175 -> REM lebih baik dari CEM
cat("Uji Hausman : p =", signif(hausman$p.value, 4), "->",
ifelse(hausman$p.value < alpha, "FEM lebih baik dari REM",
"REM lebih baik dari FEM"), "\n")
## Uji Hausman : p = 0.3119 -> REM lebih baik dari FEM
model_terpilih <- if (chow$p.value >= alpha && bp_lm$p.value >= alpha) {
"CEM"
} else if (chow$p.value < alpha && bp_lm$p.value >= alpha) {
"FEM"
} else if (chow$p.value >= alpha && bp_lm$p.value < alpha) {
"REM"
} else {
ifelse(hausman$p.value < alpha, "FEM", "REM")
}
cat("Model terpilih:", model_terpilih, "\n\n")
## Model terpilih: REM
———————————————————————
5. TWO-WAY EFFECTS (INDIVIDU + WAKTU)
———————————————————————
fem_tw <- plm(form, data = pdata, model = "within", effect = "twoways")
summary(fem_tw)
## Twoways effects Within Model
##
## Call:
## plm(formula = form, data = pdata, effect = "twoways", model = "within")
##
## Balanced Panel: n = 10, T = 20, N = 200
##
## Residuals:
## Min. 1st Qu. Median 3rd Qu. Max.
## -162.6094 -19.4710 -1.2669 19.1277 211.8420
##
## Coefficients:
## Estimate Std. Error t-value Pr(>|t|)
## value 0.117716 0.013751 8.5604 6.653e-15 ***
## capital 0.357916 0.022719 15.7540 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Total Sum of Squares: 1615600
## Residual Sum of Squares: 452150
## R-Squared: 0.72015
## Adj. R-Squared: 0.67047
## F-statistic: 217.442 on 2 and 169 DF, p-value: < 2.22e-16
pFtest(fem_tw, fem) # perlu efek waktu? p < 0.05 -> ya
##
## F test for twoways effects
##
## data: form
## F = 1.4032, df1 = 19, df2 = 169, p-value = 0.1309
## alternative hypothesis: significant effects
# Uji LM untuk efek individu, waktu, dan keduanya
plmtest(cem, effect = "individual", type = "bp")
##
## Lagrange Multiplier Test - (Breusch-Pagan)
##
## data: form
## chisq = 798.16, df = 1, p-value < 2.2e-16
## alternative hypothesis: significant effects
plmtest(cem, effect = "time", type = "bp")
##
## Lagrange Multiplier Test - time effects (Breusch-Pagan)
##
## data: form
## chisq = 6.4539, df = 1, p-value = 0.01107
## alternative hypothesis: significant effects
plmtest(cem, effect = "twoways", type = "bp")
##
## Lagrange Multiplier Test - two-ways effects (Breusch-Pagan)
##
## data: form
## chisq = 804.62, df = 2, p-value < 2.2e-16
## alternative hypothesis: significant effects
# REM two-way (opsional)
rem_tw <- plm(form, data = pdata, model = "random", effect = "twoways")
phtest(fem_tw, rem_tw)
##
## Hausman Test
##
## data: form
## chisq = 13.46, df = 2, p-value = 0.001194
## alternative hypothesis: one model is inconsistent
———————————————————————
6. UJI ASUMSI
———————————————————————
# 6a. Heteroskedastisitas (Breusch-Pagan, dengan dummy unit)
bptest(inv ~ value + capital + factor(firm), data = Grunfeld)
##
## studentized Breusch-Pagan test
##
## data: inv ~ value + capital + factor(firm)
## BP = 85.836, df = 11, p-value = 1.086e-13
# 6b. Autokorelasi serial
pbgtest(fem) # Breusch-Godfrey panel
##
## Breusch-Godfrey/Wooldridge test for serial correlation in panel models
##
## data: form
## chisq = 65.063, df = 20, p-value = 1.14e-06
## alternative hypothesis: serial correlation in idiosyncratic errors
pwartest(fem) # Wooldridge
##
## Wooldridge's test for serial correlation in FE panels
##
## data: fem
## F = 76.929, df1 = 1, df2 = 188, p-value = 1.057e-15
## alternative hypothesis: serial correlation
pdwtest(fem) # Durbin-Watson panel
##
## Durbin-Watson test for serial correlation in panel models
##
## data: form
## DW = 1.0789, p-value = 3.184e-11
## alternative hypothesis: serial correlation in idiosyncratic errors
# 6c. Dependensi antarunit (cross-sectional dependence)
pcdtest(fem, test = "cd") # Pesaran CD
##
## Pesaran CD test for cross-sectional dependence in panels
##
## data: inv ~ value + capital
## z = 4.6612, p-value = 3.144e-06
## alternative hypothesis: cross-sectional dependence
pcdtest(fem, test = "lm") # Breusch-Pagan LM
##
## Breusch-Pagan LM test for cross-sectional dependence in panels
##
## data: inv ~ value + capital
## chisq = 246.33, df = 45, p-value < 2.2e-16
## alternative hypothesis: cross-sectional dependence
# 6d. Multikolinearitas
vif(lm(inv ~ value + capital, data = Grunfeld))
## value capital
## 1.313773 1.313773
cor(Grunfeld[, c("value", "capital")])
## value capital
## value 1.0000000 0.4887058
## capital 0.4887058 1.0000000
# 6e. Normalitas residual (informatif)
res_fem <- residuals(fem)
shapiro.test(as.numeric(res_fem))
##
## Shapiro-Wilk normality test
##
## data: as.numeric(res_fem)
## W = 0.90975, p-value = 1.1e-09
qqnorm(as.numeric(res_fem)); qqline(as.numeric(res_fem))

# 6f. Akar unit / stasioneritas
purtest(pdata$inv, test = "levinlin", exo = "intercept",
lags = "AIC", pmax = 4)
## Warning in selectT(l, theTs): the time series is short
##
## Levin-Lin-Chu Unit-Root Test (ex. var.: Individual Intercepts)
##
## data: pdata$inv
## z = 3.1416, p-value = 0.9992
## alternative hypothesis: stationarity
purtest(pdata$value, test = "levinlin", exo = "intercept",
lags = "AIC", pmax = 4)
## Warning in selectT(l, theTs): the time series is short
##
## Levin-Lin-Chu Unit-Root Test (ex. var.: Individual Intercepts)
##
## data: pdata$value
## z = 1.7905, p-value = 0.9633
## alternative hypothesis: stationarity
purtest(pdata$capital, test = "levinlin", exo = "intercept",
lags = "AIC", pmax = 4)
## Warning in selectT(l, theTs): the time series is short
##
## Levin-Lin-Chu Unit-Root Test (ex. var.: Individual Intercepts)
##
## data: pdata$capital
## z = 3.5537, p-value = 0.9998
## alternative hypothesis: stationarity
# Alternatif (lebih toleran terhadap heterogenitas antar unit)
purtest(pdata$inv, test = "ips", exo = "intercept", lags = "AIC", pmax = 4)
##
## Im-Pesaran-Shin Unit-Root Test (ex. var.: Individual Intercepts)
##
## data: pdata$inv
## Wtbar = 3.0768, p-value = 0.999
## alternative hypothesis: stationarity
———————————————————————
7. PENANGANAN PELANGGARAN: STANDARD ERROR ROBUST
———————————————————————
# Cluster per unit (robust terhadap heteroskedastisitas & autokorelasi)
coeftest(fem, vcov = vcovHC(fem, type = "HC1", cluster = "group"))
##
## t test of coefficients:
##
## Estimate Std. Error t value Pr(>|t|)
## value 0.110124 0.014414 7.6398 1.076e-12 ***
## capital 0.310065 0.050043 6.1959 3.576e-09 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# Driscoll-Kraay (jika ada cross-sectional dependence)
coeftest(fem, vcov = vcovSCC(fem, type = "HC1"))
##
## t test of coefficients:
##
## Estimate Std. Error t value Pr(>|t|)
## value 0.110124 0.017775 6.1954 3.586e-09 ***
## capital 0.310065 0.034996 8.8601 6.017e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# Perbandingan SE biasa vs robust
se_biasa <- sqrt(diag(vcov(fem)))
se_cluster <- sqrt(diag(vcovHC(fem, type = "HC1", cluster = "group")))
se_dk <- sqrt(diag(vcovSCC(fem, type = "HC1")))
print(round(cbind(SE_biasa = se_biasa, SE_cluster = se_cluster,
SE_DriscollKraay = se_dk), 4))
## SE_biasa SE_cluster SE_DriscollKraay
## value 0.0119 0.0144 0.0178
## capital 0.0174 0.0500 0.0350
# Tabel akhir dengan SE robust
stargazer(fem, fem, type = "text",
se = list(se_biasa, se_cluster),
column.labels = c("FEM (SE biasa)", "FEM (SE cluster)"),
model.names = FALSE)
##
## =========================================================
## Dependent variable:
## -------------------------------
## inv
## FEM (SE biasa) FEM (SE cluster)
## (1) (2)
## ---------------------------------------------------------
## value 0.110*** 0.110***
## (0.012) (0.014)
##
## capital 0.310*** 0.310***
## (0.017) (0.050)
##
## ---------------------------------------------------------
## Observations 200 200
## R2 0.767 0.767
## Adjusted R2 0.753 0.753
## F Statistic (df = 2; 188) 309.014*** 309.014***
## =========================================================
## Note: *p<0.1; **p<0.05; ***p<0.01
———————————————————————
8. MODEL AKHIR DAN INTERPRETASI
———————————————————————
Ganti ‘fem’ dengan model_terpilih bila hasilnya REM / CEM
model_akhir <- switch(model_terpilih, CEM = cem, FEM = fem, REM = rem)
cat("\n===== MODEL AKHIR:", model_terpilih, "(SE cluster per unit) =====\n")
##
## ===== MODEL AKHIR: REM (SE cluster per unit) =====
print(coeftest(model_akhir,
vcov = vcovHC(model_akhir, type = "HC1", cluster = "group")))
##
## t test of coefficients:
##
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -57.834415 23.627502 -2.4478 0.01525 *
## value 0.109781 0.013083 8.3914 9.224e-15 ***
## capital 0.308113 0.052283 5.8932 1.618e-08 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# R-squared model akhir
r.squared(model_akhir)
## [1] 0.7695027
# Nilai prediksi vs aktual (FEM)
aktual <- as.numeric(pdata$inv)
fitted_fem <- aktual - as.numeric(residuals(fem))
plot(fitted_fem, aktual, pch = 16, xlab = "Fitted", ylab = "Aktual",
main = "Aktual vs Fitted (FEM)")
abline(0, 1, col = "red")
