library(haven)
library(psych)
library(GPArotation)
library(dplyr)
library(tidyr)
library(forcats)
library(corrplot)
library(ggplot2)
library(knitr)
library(kableExtra)
library(kirkegaard)
figs_dir <- "figs"
dir.create(figs_dir, showWarnings = FALSE)
lew_data <- read_sav("Lewandowsky.sav")
# 14 conspiracy items (1–4 scale: strongly disagree to strongly agree)
cy_items <- c(
"CYNewWorldOrder", "CYSARS", "CYPearlHarbor", "CYAIDS",
"CYMLK", "CYMoon", "CYJFK", "CY911",
"CYDiana", "CYOkla", "CYCoke", "CYArea51",
"CYRoswell", "CYClimChange"
)
cy_labels <- c(
"New World Order", "SARS", "Pearl Harbor", "AIDS",
"MLK", "Moon landing", "JFK", "9/11",
"Diana", "Oklahoma City", "Coca-Cola", "Area 51",
"Roswell", "Climate change"
)
fa_data <- lew_data %>% select(all_of(cy_items)) %>% na.omit()
Item wordings are from Table 1 of Lewandowsky et al. (2012). All items used a 4-point scale from strongly disagree (1) to strongly agree (4).
item_wordings <- tibble::tibble(
Variable = cy_items,
Label = cy_labels,
Item = c(
"A powerful and secretive group known as the New World Order is planning to eventually rule the world through an autonomous world government that would replace sovereign governments.",
"SARS (Severe Acute Respiratory Syndrome) was produced under laboratory conditions as a biological weapon.",
"The U.S. government had foreknowledge about the Japanese attack on Pearl Harbor but allowed the attack to take place so as to be able to enter the Second World War.",
"U.S. agencies intentionally created the AIDS epidemic and administered it to Black and gay men in the 1970s.",
"The assassination of Martin Luther King Jr. was the result of an organized conspiracy by U.S. government agencies such as the FBI and CIA.",
"The Apollo moon landings never happened and were staged in a Hollywood film studio.",
"The assassination of John F. Kennedy was not committed by the lone gunman Lee Harvey Oswald but was rather a detailed organized conspiracy to kill the president.",
"The U.S. government allowed the 9/11 attacks to take place so that it would have an excuse to achieve foreign and domestic goals that had been determined prior to the attacks.",
"Princess Diana's death was not an accident but rather an organized assassination by members of the British royal family who disliked her.",
"The Oklahoma City bombers Timothy McVeigh and Terry Nichols did not act alone but rather received assistance from neo-Nazi groups.",
"The Coca-Cola company intentionally changed to an inferior formula with the intent of driving up demand for their classic product, later reintroducing it for their financial gain.",
"Area 51 in Nevada is a secretive military base that contains hidden alien spacecraft and/or alien bodies.",
"In July 1947, the U.S. military recovered the wreckage of an alien spacecraft from Roswell, NM, and covered up the fact.",
"The claim that the climate is changing due to emissions from fossil fuels is a hoax perpetrated by corrupt scientists who want to spend more taxpayer money on climate research."
)
)
item_wordings %>%
kable(caption = "Conspiracy belief items (Lewandowsky et al., 2012, Table 1)") %>%
kable_styling(bootstrap_options = c("striped", "hover"), full_width = TRUE) %>%
column_spec(3, width = "60%")
| Variable | Label | Item |
|---|---|---|
| CYNewWorldOrder | New World Order | A powerful and secretive group known as the New World Order is planning to eventually rule the world through an autonomous world government that would replace sovereign governments. |
| CYSARS | SARS | SARS (Severe Acute Respiratory Syndrome) was produced under laboratory conditions as a biological weapon. |
| CYPearlHarbor | Pearl Harbor | The U.S. government had foreknowledge about the Japanese attack on Pearl Harbor but allowed the attack to take place so as to be able to enter the Second World War. |
| CYAIDS | AIDS | U.S. agencies intentionally created the AIDS epidemic and administered it to Black and gay men in the 1970s. |
| CYMLK | MLK | The assassination of Martin Luther King Jr. was the result of an organized conspiracy by U.S. government agencies such as the FBI and CIA. |
| CYMoon | Moon landing | The Apollo moon landings never happened and were staged in a Hollywood film studio. |
| CYJFK | JFK | The assassination of John F. Kennedy was not committed by the lone gunman Lee Harvey Oswald but was rather a detailed organized conspiracy to kill the president. |
| CY911 | 9/11 | The U.S. government allowed the 9/11 attacks to take place so that it would have an excuse to achieve foreign and domestic goals that had been determined prior to the attacks. |
| CYDiana | Diana | Princess Diana’s death was not an accident but rather an organized assassination by members of the British royal family who disliked her. |
| CYOkla | Oklahoma City | The Oklahoma City bombers Timothy McVeigh and Terry Nichols did not act alone but rather received assistance from neo-Nazi groups. |
| CYCoke | Coca-Cola | The Coca-Cola company intentionally changed to an inferior formula with the intent of driving up demand for their classic product, later reintroducing it for their financial gain. |
| CYArea51 | Area 51 | Area 51 in Nevada is a secretive military base that contains hidden alien spacecraft and/or alien bodies. |
| CYRoswell | Roswell | In July 1947, the U.S. military recovered the wreckage of an alien spacecraft from Roswell, NM, and covered up the fact. |
| CYClimChange | Climate change | The claim that the climate is changing due to emissions from fossil fuels is a hoax perpetrated by corrupt scientists who want to spend more taxpayer money on climate research. |
Most items are heavily skewed toward 1 (disagree). The 1–4 ordinal scale warrants polychoric (latent) correlations.
dist_data <- fa_data %>%
pivot_longer(everything(), names_to = "item", values_to = "response") %>%
mutate(item = factor(item, levels = cy_items, labels = cy_labels)) %>%
group_by(item, response) %>%
summarise(n = n(), .groups = "drop") %>%
group_by(item) %>%
mutate(pct = n / sum(n)) %>%
ungroup() %>%
# Order items by mean response (i.e., endorsement)
left_join(
fa_data %>%
pivot_longer(everything(), names_to = "item", values_to = "response") %>%
mutate(item = factor(item, levels = cy_items, labels = cy_labels)) %>%
group_by(item) %>%
summarise(mean_resp = mean(response), .groups = "drop"),
by = "item"
) %>%
mutate(
item = fct_reorder(item, mean_resp),
response = factor(response, levels = 1:4,
labels = c("Strongly disagree", "Disagree", "Agree", "Strongly agree"))
)
ggplot(dist_data, aes(x = item, y = pct, fill = response)) +
geom_bar(stat = "identity") +
geom_text(
aes(label = ifelse(pct >= 0.04, paste0(round(pct * 100), "%"), "")),
position = position_stack(vjust = 0.5), size = 3
) +
coord_flip() +
scale_y_continuous("Percentage", labels = scales::percent) +
scale_fill_brewer(palette = "Paired", name = "Response") +
labs(x = NULL, title = "Response distributions (ordered by mean endorsement)") +
theme_bw()
GG_save(file.path(figs_dir, "distributions.png"))
Because the items are ordinal (4-point scale), we use polychoric correlations to estimate the latent correlations.
poly <- polychoric(fa_data)
R_poly <- poly$rho
colnames(R_poly) <- rownames(R_poly) <- cy_labels
corrplot(
R_poly,
method = "color",
type = "lower",
addCoef.col = "black",
number.cex = 0.6,
tl.cex = 0.8,
tl.col = "black",
col = colorRampPalette(c("#2166AC", "white", "#B2182B"))(200),
title = "Polychoric correlation matrix of conspiracy items",
mar = c(0, 0, 2, 0)
)
png(file.path(figs_dir, "corrplot.png"), width = 9, height = 9, units = "in", res = 300)
corrplot(
R_poly, method = "color", type = "lower", addCoef.col = "black",
number.cex = 0.6, tl.cex = 0.8, tl.col = "black",
col = colorRampPalette(c("#2166AC", "white", "#B2182B"))(200),
title = "Polychoric correlation matrix of conspiracy items",
mar = c(0, 0, 2, 0)
)
invisible(dev.off())
The correlation matrix shows a near-positive manifold: almost all inter-item correlations are positive, suggesting a general conspiracy-belief factor accounts for the bulk of shared variance. However, the magnitudes vary considerably — some items (e.g., Moon landing, AIDS) correlate weakly with others.
fa.parallel(
R_poly, n.obs = nrow(fa_data), fa = "both", fm = "pa",
main = "Parallel analysis scree plot (polychoric)"
)
## Parallel analysis suggests that the number of factors = 5 and the number of components = 2
png(file.path(figs_dir, "scree.png"), width = 7, height = 5, units = "in", res = 300)
fa.parallel(R_poly, n.obs = nrow(fa_data), fa = "both", fm = "pa",
main = "Parallel analysis scree plot (polychoric)")
## Parallel analysis suggests that the number of factors = 5 and the number of components = 2
invisible(dev.off())
The scree plot shows a dominant first eigenvalue with a sharp drop-off, consistent with a strong general factor. The second eigenvalue is near the parallel analysis threshold, making the case for a second factor marginal.
We compare extraction methods on the polychoric correlation matrix. Both 1-factor and 2-factor solutions are examined, since the scree plot indicates the variance is dominated by a general factor.
print_loadings <- function(fa_obj, title) {
ld <- as.data.frame(unclass(fa_obj$loadings))
ld$Item <- cy_labels[match(rownames(ld), cy_items)]
if (is.null(ld$Item)) ld$Item <- rownames(ld)
ld$h2 <- fa_obj$communalities
ld %>%
select(Item, everything()) %>%
kable(digits = 3, caption = title) %>%
kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
}
eigen_vals <- eigen(R_poly)$values
n_kaiser <- sum(eigen_vals > 1)
fa_paf_1 <- fa(
r = R_poly, n.obs = nrow(fa_data),
nfactors = 1, fm = "pa"
)
print(fa_paf_1, cut = 0.2, sort = TRUE)
## Factor Analysis using method = pa
## Call: fa(r = R_poly, nfactors = 1, n.obs = nrow(fa_data), fm = "pa")
## Standardized loadings (pattern matrix) based upon correlation matrix
## V PA1 h2 u2 com
## AIDS 4 0.87 0.759 0.24 1
## Diana 9 0.82 0.665 0.33 1
## Moon landing 6 0.80 0.638 0.36 1
## 9/11 8 0.79 0.629 0.37 1
## Roswell 13 0.78 0.604 0.40 1
## Area 51 12 0.77 0.588 0.41 1
## SARS 2 0.74 0.554 0.45 1
## MLK 5 0.74 0.548 0.45 1
## JFK 7 0.71 0.507 0.49 1
## New World Order 1 0.69 0.472 0.53 1
## Pearl Harbor 3 0.65 0.425 0.57 1
## Coca-Cola 11 0.61 0.371 0.63 1
## Oklahoma City 10 0.42 0.180 0.82 1
## Climate change 14 0.29 0.086 0.91 1
##
## PA1
## SS loadings 7.03
## Proportion Var 0.50
##
## Mean item complexity = 1
## Test of the hypothesis that 1 factor is sufficient.
##
## df null model = 91 with the objective function = 10.62 with Chi Square = 12091.13
## df of the model are 77 and the objective function was 2.95
##
## The root mean square of the residuals (RMSR) is 0.09
## The df corrected root mean square of the residuals is 0.09
##
## The harmonic n.obs is 1145 with the empirical chi square 1524.3 with prob < 1.5e-267
## The total n.obs was 1145 with Likelihood Chi Square = 3356.73 with prob < 0
##
## Tucker Lewis Index of factoring reliability = 0.677
## RMSEA index = 0.193 and the 90 % confidence intervals are 0.187 0.199
## BIC = 2814.41
## Fit based upon off diagonal values = 0.97
## Measures of factor score adequacy
## PA1
## Correlation of (regression) scores with factors 0.97
## Multiple R square of scores with factors 0.95
## Minimum correlation of possible factor scores 0.90
print_loadings(fa_paf_1, "PAF — 1 factor")
| Item | PA1 | h2 | |
|---|---|---|---|
| New World Order | NA | 0.687 | 7.025 |
| SARS | NA | 0.744 | 7.025 |
| Pearl Harbor | NA | 0.652 | 7.025 |
| AIDS | NA | 0.871 | 7.025 |
| MLK | NA | 0.741 | 7.025 |
| Moon landing | NA | 0.799 | 7.025 |
| JFK | NA | 0.712 | 7.025 |
| 9/11 | NA | 0.793 | 7.025 |
| Diana | NA | 0.816 | 7.025 |
| Oklahoma City | NA | 0.424 | 7.025 |
| Coca-Cola | NA | 0.609 | 7.025 |
| Area 51 | NA | 0.767 | 7.025 |
| Roswell | NA | 0.777 | 7.025 |
| Climate change | NA | 0.293 | 7.025 |
fa_ml_1 <- fa(
r = R_poly, n.obs = nrow(fa_data),
nfactors = 1, fm = "ml"
)
print_loadings(fa_ml_1, "ML — 1 factor")
| Item | ML1 | h2 | |
|---|---|---|---|
| New World Order | NA | 0.689 | 0.475 |
| SARS | NA | 0.751 | 0.564 |
| Pearl Harbor | NA | 0.652 | 0.426 |
| AIDS | NA | 0.875 | 0.766 |
| MLK | NA | 0.741 | 0.549 |
| Moon landing | NA | 0.814 | 0.662 |
| JFK | NA | 0.687 | 0.473 |
| 9/11 | NA | 0.794 | 0.631 |
| Diana | NA | 0.812 | 0.660 |
| Oklahoma City | NA | 0.420 | 0.176 |
| Coca-Cola | NA | 0.608 | 0.369 |
| Area 51 | NA | 0.761 | 0.579 |
| Roswell | NA | 0.773 | 0.597 |
| Climate change | NA | 0.307 | 0.094 |
pca_1 <- principal(
R_poly, nfactors = 1,
n.obs = nrow(fa_data)
)
print_loadings(pca_1, "PCA — 1 component")
| Item | PC1 | |
|---|---|---|
| New World Order | NA | 0.718 |
| SARS | NA | 0.768 |
| Pearl Harbor | NA | 0.685 |
| AIDS | NA | 0.874 |
| MLK | NA | 0.765 |
| Moon landing | NA | 0.814 |
| JFK | NA | 0.741 |
| 9/11 | NA | 0.809 |
| Diana | NA | 0.829 |
| Oklahoma City | NA | 0.461 |
| Coca-Cola | NA | 0.645 |
| Area 51 | NA | 0.787 |
| Roswell | NA | 0.796 |
| Climate change | NA | 0.322 |
The 1-factor solution is broadly consistent across all three extraction methods. Loadings vary across items — some (e.g., New World Order, SARS, 9/11, Roswell) load moderately, while others (Moon landing, AIDS, Oklahoma City) load weakly, indicating they are poor indicators of a general conspiracy factor.
This replicates the original SPSS analysis.
fa_paf_2 <- fa(
r = R_poly, n.obs = nrow(fa_data),
nfactors = n_kaiser, rotate = "oblimin",
fm = "pa", normalize = TRUE
)
print(fa_paf_2, cut = 0.2, sort = TRUE)
## Factor Analysis using method = pa
## Call: fa(r = R_poly, nfactors = n_kaiser, n.obs = nrow(fa_data), rotate = "oblimin",
## fm = "pa", normalize = TRUE)
## Standardized loadings (pattern matrix) based upon correlation matrix
## item PA1 PA2 h2 u2 com
## 9/11 8 0.86 0.71 0.29 1.1
## MLK 5 0.85 -0.26 0.71 0.29 1.2
## AIDS 4 0.81 0.21 0.76 0.24 1.1
## Diana 9 0.78 0.66 0.34 1.0
## JFK 7 0.75 0.54 0.46 1.0
## Moon landing 6 0.71 0.28 0.66 0.34 1.3
## Pearl Harbor 3 0.69 0.46 0.54 1.0
## Roswell 13 0.69 0.27 0.63 0.37 1.3
## SARS 2 0.69 0.56 0.44 1.1
## Area 51 12 0.69 0.26 0.61 0.39 1.3
## Coca-Cola 11 0.60 0.37 0.63 1.0
## New World Order 1 0.55 0.45 0.60 0.40 1.9
## Oklahoma City 10 0.52 -0.26 0.28 0.72 1.5
## Climate change 14 0.73 0.56 0.44 1.0
##
## PA1 PA2
## SS loadings 6.77 1.34
## Proportion Var 0.48 0.10
## Cumulative Var 0.48 0.58
## Proportion Explained 0.83 0.17
## Cumulative Proportion 0.83 1.00
##
## With factor correlations of
## PA1 PA2
## PA1 1.0 0.2
## PA2 0.2 1.0
##
## Mean item complexity = 1.2
## Test of the hypothesis that 2 factors are sufficient.
##
## df null model = 91 with the objective function = 10.62 with Chi Square = 12091.13
## df of the model are 64 and the objective function was 2.16
##
## The root mean square of the residuals (RMSR) is 0.05
## The df corrected root mean square of the residuals is 0.06
##
## The harmonic n.obs is 1145 with the empirical chi square 590.75 with prob < 2.7e-86
## The total n.obs was 1145 with Likelihood Chi Square = 2453.09 with prob < 0
##
## Tucker Lewis Index of factoring reliability = 0.717
## RMSEA index = 0.181 and the 90 % confidence intervals are 0.175 0.187
## BIC = 2002.33
## Fit based upon off diagonal values = 0.99
## Measures of factor score adequacy
## PA1 PA2
## Correlation of (regression) scores with factors 0.97 0.87
## Multiple R square of scores with factors 0.95 0.75
## Minimum correlation of possible factor scores 0.89 0.50
print_loadings(fa_paf_2, "PAF with oblimin rotation — 2 factors")
| Item | PA1 | PA2 | h2 | |
|---|---|---|---|---|
| New World Order | NA | 0.553 | 0.446 | 8.119 |
| SARS | NA | 0.687 | 0.183 | 8.119 |
| Pearl Harbor | NA | 0.694 | -0.099 | 8.119 |
| AIDS | NA | 0.805 | 0.212 | 8.119 |
| MLK | NA | 0.853 | -0.264 | 8.119 |
| Moon landing | NA | 0.711 | 0.279 | 8.119 |
| JFK | NA | 0.750 | -0.085 | 8.119 |
| 9/11 | NA | 0.860 | -0.155 | 8.119 |
| Diana | NA | 0.785 | 0.105 | 8.119 |
| Oklahoma City | NA | 0.521 | -0.257 | 8.119 |
| Coca-Cola | NA | 0.601 | 0.035 | 8.119 |
| Area 51 | NA | 0.686 | 0.256 | 8.119 |
| Roswell | NA | 0.694 | 0.265 | 8.119 |
| Climate change | NA | 0.064 | 0.734 | 8.119 |
fa_ml_2 <- fa(
r = R_poly, n.obs = nrow(fa_data),
nfactors = n_kaiser, rotate = "oblimin",
fm = "ml", normalize = TRUE
)
print_loadings(fa_ml_2, "ML with oblimin rotation — 2 factors")
| Item | ML1 | ML2 | h2 | |
|---|---|---|---|---|
| New World Order | NA | 0.547 | 0.169 | 0.457 |
| SARS | NA | 0.638 | 0.140 | 0.551 |
| Pearl Harbor | NA | 0.736 | -0.075 | 0.470 |
| AIDS | NA | 0.885 | 0.002 | 0.787 |
| MLK | NA | 0.925 | -0.185 | 0.650 |
| Moon landing | NA | 0.582 | 0.283 | 0.650 |
| JFK | NA | 0.573 | 0.165 | 0.488 |
| 9/11 | NA | 0.843 | -0.025 | 0.681 |
| Diana | NA | 0.679 | 0.168 | 0.649 |
| Oklahoma City | NA | 0.436 | -0.002 | 0.189 |
| Coca-Cola | NA | 0.535 | 0.093 | 0.364 |
| Area 51 | NA | 0.014 | 0.938 | 0.899 |
| Roswell | NA | 0.040 | 0.922 | 0.904 |
| Climate change | NA | 0.075 | 0.255 | 0.098 |
pca_2 <- principal(
R_poly, nfactors = n_kaiser, rotate = "oblimin",
n.obs = nrow(fa_data)
)
print_loadings(pca_2, "PCA with oblimin rotation — 2 components")
| Item | TC1 | TC2 | |
|---|---|---|---|
| New World Order | NA | 0.594 | 0.474 |
| SARS | NA | 0.727 | 0.165 |
| Pearl Harbor | NA | 0.732 | -0.162 |
| AIDS | NA | 0.827 | 0.189 |
| MLK | NA | 0.849 | -0.300 |
| Moon landing | NA | 0.746 | 0.267 |
| JFK | NA | 0.784 | -0.149 |
| 9/11 | NA | 0.863 | -0.184 |
| Diana | NA | 0.814 | 0.071 |
| Oklahoma City | NA | 0.589 | -0.465 |
| Coca-Cola | NA | 0.651 | -0.010 |
| Area 51 | NA | 0.727 | 0.239 |
| Roswell | NA | 0.734 | 0.245 |
| Climate change | NA | 0.095 | 0.852 |
The 2-factor solution is unstable across extraction methods. The second factor changes identity depending on the method: ML extracts an aliens/space factor (Area 51 and Roswell loading strongly), while PAF extracts a climate factor where only the climate change item loads heavily — a degenerate single-item factor. Items shift between factors depending on the method, and neither second factor is substantively compelling. This instability, combined with the marginal second eigenvalue and the near-positive manifold in the correlation matrix, suggests the 2-factor solution is not robust. The data are better described by a single general factor with varying item quality.
pa_result <- fa.parallel(
R_poly, n.obs = nrow(fa_data), fa = "fa", fm = "pa",
plot = FALSE
)
## Parallel analysis suggests that the number of factors = 5 and the number of components = NA
n_pa <- pa_result$nfact
if (n_pa > n_kaiser) {
fa_paf_pa <- fa(
r = R_poly, n.obs = nrow(fa_data),
nfactors = n_pa, rotate = "oblimin",
fm = "pa", normalize = TRUE
)
print_loadings(fa_paf_pa, paste0("PAF with oblimin rotation (parallel analysis: ", n_pa, " factors)"))
}
| Item | PA1 | PA3 | PA4 | PA2 | PA5 | h2 | |
|---|---|---|---|---|---|---|---|
| New World Order | NA | 0.319 | 0.116 | 0.050 | 0.479 | 0.055 | 9.936 |
| SARS | NA | 0.155 | 0.145 | 0.390 | 0.195 | 0.209 | 9.936 |
| Pearl Harbor | NA | 0.683 | 0.033 | 0.009 | 0.030 | -0.063 | 9.936 |
| AIDS | NA | 0.572 | 0.014 | 0.167 | 0.231 | 0.359 | 9.936 |
| MLK | NA | 0.631 | -0.072 | 0.321 | -0.017 | -0.056 | 9.936 |
| Moon landing | NA | 0.201 | 0.319 | 0.220 | 0.156 | 0.332 | 9.936 |
| JFK | NA | 0.367 | 0.141 | 0.380 | 0.211 | -0.511 | 9.936 |
| 9/11 | NA | 0.872 | 0.126 | -0.057 | -0.117 | 0.053 | 9.936 |
| Diana | NA | 0.198 | 0.198 | 0.421 | 0.149 | 0.146 | 9.936 |
| Oklahoma City | NA | -0.011 | 0.033 | 0.580 | -0.098 | -0.052 | 9.936 |
| Coca-Cola | NA | 0.126 | 0.131 | 0.374 | 0.082 | 0.113 | 9.936 |
| Area 51 | NA | -0.009 | 1.049 | -0.063 | -0.041 | -0.034 | 9.936 |
| Roswell | NA | -0.029 | 0.885 | 0.071 | 0.030 | -0.005 | 9.936 |
| Climate change | NA | -0.139 | 0.000 | -0.105 | 1.045 | -0.030 | 9.936 |
fa.diagram(fa_paf_1, main = "PAF — 1 factor", cut = 0.2)
png(file.path(figs_dir, "diagram_1f.png"), width = 8, height = 6, units = "in", res = 300)
fa.diagram(fa_paf_1, main = "PAF — 1 factor", cut = 0.2)
invisible(dev.off())
fa.diagram(fa_paf_2, main = "PAF — 2 factors (oblimin)", cut = 0.2)
png(file.path(figs_dir, "diagram_2f.png"), width = 10, height = 6, units = "in", res = 300)
fa.diagram(fa_paf_2, main = "PAF — 2 factors (oblimin)", cut = 0.2)
invisible(dev.off())
We score both the 1-factor and 2-factor PAF solutions and correlate them with the external variables in the dataset: free market ideology, climate science acceptance, other science acceptance, and perceived environmental problem resolution.
Note: this dataset contains no demographic variables (age, gender, education, etc.). The “external” variables are all attitudinal scales from the same survey.
# 1-factor scores
fa_scored_1 <- fa(
r = fa_data, nfactors = 1,
fm = "pa", scores = "regression"
)
# 2-factor scores
fa_scored_2 <- fa(
r = fa_data, nfactors = n_kaiser,
rotate = "oblimin", fm = "pa",
normalize = TRUE, scores = "regression"
)
scores_1f <- as.data.frame(fa_scored_1$scores)
names(scores_1f) <- "General_conspiracy"
scores_2f <- as.data.frame(fa_scored_2$scores)
names(scores_2f) <- paste0("Factor", 1:n_kaiser)
# Bind factor scores to the complete-case rows
scored_data <- lew_data %>%
select(all_of(cy_items)) %>%
mutate(.row = row_number()) %>%
na.omit()
full_scored <- lew_data[scored_data$.row, ] %>%
bind_cols(scores_1f) %>%
bind_cols(scores_2f)
# Define external variable groups
ext_flat <- c(
"FreeMarket",
"FMUnresBest", "FMNotEnvQual", "FMLimitSocial",
"FMMoreImp", "FMThreatEnv", "FMUnsustain",
"AcceptClimSci",
"CO2TempUp", "CO2AtmosUp", "CO2WillNegChange", "CO2HasNegChange",
"CauseHIV", "CauseSmoke", "CauseCO2",
"ConsensHIV", "ConsensSmoke", "ConsensCO2",
"CFCNowOK", "AcidRainNowOK"
)
factor_names <- c("General_conspiracy", paste0("Factor", 1:n_kaiser))
cor_mat <- cor(
full_scored[, factor_names],
full_scored[, ext_flat],
use = "pairwise.complete.obs"
)
as.data.frame(t(round(cor_mat, 3))) %>%
mutate(Variable = rownames(.)) %>%
select(Variable, everything()) %>%
kable(digits = 3, caption = "Correlations: factor scores with external variables") %>%
kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
| Variable | General_conspiracy | Factor1 | Factor2 | |
|---|---|---|---|---|
| FreeMarket | FreeMarket | 0.036 | -0.095 | 0.256 |
| FMUnresBest | FMUnresBest | 0.013 | -0.104 | 0.213 |
| FMNotEnvQual | FMNotEnvQual | 0.109 | 0.097 | 0.102 |
| FMLimitSocial | FMLimitSocial | 0.028 | -0.055 | 0.165 |
| FMMoreImp | FMMoreImp | 0.038 | -0.067 | 0.211 |
| FMThreatEnv | FMThreatEnv | 0.026 | -0.090 | 0.221 |
| FMUnsustain | FMUnsustain | 0.043 | -0.071 | 0.231 |
| AcceptClimSci | AcceptClimSci | -0.157 | -0.011 | -0.371 |
| CO2TempUp | CO2TempUp | -0.172 | -0.039 | -0.359 |
| CO2AtmosUp | CO2AtmosUp | -0.171 | -0.029 | -0.373 |
| CO2WillNegChange | CO2WillNegChange | -0.145 | 0.000 | -0.360 |
| CO2HasNegChange | CO2HasNegChange | -0.107 | 0.019 | -0.301 |
| CauseHIV | CauseHIV | -0.338 | -0.266 | -0.370 |
| CauseSmoke | CauseSmoke | -0.292 | -0.197 | -0.379 |
| CauseCO2 | CauseCO2 | -0.216 | -0.063 | -0.426 |
| ConsensHIV | ConsensHIV | -0.147 | -0.104 | -0.185 |
| ConsensSmoke | ConsensSmoke | -0.087 | -0.044 | -0.141 |
| ConsensCO2 | ConsensCO2 | -0.199 | -0.071 | -0.371 |
| CFCNowOK | CFCNowOK | 0.050 | -0.008 | 0.133 |
| AcidRainNowOK | AcidRainNowOK | 0.047 | -0.015 | 0.138 |
cor_long <- as.data.frame(t(cor_mat)) %>%
mutate(Variable = rownames(.)) %>%
pivot_longer(-Variable, names_to = "Factor", values_to = "r") %>%
mutate(
Factor = factor(Factor, levels = factor_names),
Variable = factor(Variable, levels = rev(ext_flat))
)
ggplot(cor_long, aes(x = Factor, y = Variable, fill = r)) +
geom_tile(color = "white") +
geom_text(aes(label = sprintf("%.2f", r)), size = 3.2) +
scale_fill_gradient2(
low = "#2166AC", mid = "white", high = "#B2182B",
limits = c(-1, 1)
) +
labs(
title = "Factor score correlations with external variables",
fill = "r"
) +
theme_minimal() +
theme(axis.text.y = element_text(size = 9))
GG_save(file.path(figs_dir, "cor_heatmap.png"))