Reliability and Factor Analysis Method Card Template (Statistics, R and Python)
Survey scale checks: reverse coding, item analysis, Cronbach's alpha and omega, PCA versus EFA, parallel analysis, rotation and loadings, in R and Python
사용법: Use when you sum questionnaire items into scale scores or need to check that items group into the intended constructs. Reverse code first, then compute item statistics and alpha per scale, decide the number of factors with parallel analysis, and report rotated loadings with communalities. Main pitfall: forgetting a reverse-worded item, or treating a high alpha as proof that a scale is unidimensional or valid.
미리보기
Reliability and Factor Analysis: [Your study question or course]
A method card for checking survey scales: item analysis, reverse-coded items, Cronbach's alpha (by hand and in code), alpha if item deleted, McDonald's omega, principal component analysis (PCA) versus exploratory factor analysis (EFA), how many factors to keep (Kaiser, scree, parallel analysis), rotation (varimax versus oblique), reading a loadings table, and confirmatory factor analysis (CFA) as the next step. It is for students in a psychometrics or research methods course, master's and PhD students validating a questionnaire for a thesis, and analysts building scores from survey items. It speeds up learning by putting the decisions in a fixed order and by running base R and Python on the same item data, with a fully solved, a half solved and an unsolved example. The worked examples use fictional data; replace them with your own. Source basis: Cronbach (1951), McDonald (1999), Kaiser (1960), Cattell (1966), Horn (1965), the NIST/SEMATECH e-Handbook and the R
statsand statsmodels documentation.
Document control
| Field | Value |
|---|---|
| Course or project | [Research methods module / thesis chapter 3 / survey programme] |
| Learner or analyst | [Your name] |
| Data set | [Instrument, version, sample, n, date] Example: Lakemoor University statistics attitudes pilot, 8 items, n = 40 (fictional) |
| Scoring key | [Items per scale, reversed items] Example: Motivation mot1-mot4 (mot4 reversed), Anxiety anx1-anx4 |
| Software and versions | R 4.5.1 (base stats: factanal, prcomp); Python 3.14 with numpy 2.5.4, pandas 3.1.0, statsmodels 0.15.0 |
| Date | YYYY-MM-DD |
| Version | [0.1] |
When to use it
One-sentence rule: use reliability analysis to check that items meant to measure one thing hang together well enough to be summed, and factor analysis to check how many distinct things a set of items measures and which items belong to which.
A questionnaire scale adds several items into one score because any single item is noisy. Reliability asks how much of the variation in that sum is consistent signal rather than item-specific noise. Cronbach's alpha (Cronbach 1951) is the most widely reported index, though it assumes all items measure the construct equally well; McDonald's omega relaxes that. Factor analysis looks one level deeper: from the correlations between items, it estimates a small number of latent factors that would explain them. Principal component analysis looks similar on the screen but answers a different question: how to compress many variables into a few components that keep as much total variance as possible, with no claim about latent constructs.
| Use when | Do not use when |
|---|---|
| You will sum or average items into a scale score and need to report its reliability | Items are a checklist of different events (a "formative" index such as a list of stressors): high inter-item correlation is not expected |
| You are piloting or adapting a questionnaire and need to check that items group as intended (EFA) | You already have a theory of which items load where and want to test it: use CFA |
| You want fewer variables for a later model or a plot (PCA) | n is tiny relative to items (fewer than about 5 respondents per item, or under 50 overall) and you want stable loadings: treat results as exploratory only |
| Items are ordinal with 5 or more categories and roughly symmetric | Items are binary or very skewed: use polychoric or tetrachoric correlations, or item response theory |
Alternatives: McDonald's omega instead of (or with) alpha; test-retest correlation or intraclass correlation for
stability over time; CFA with structural equation modelling software (R lavaan, Python semopy); item response
theory models for ordinal items.
The question and the data
Question: a Lakemoor University teaching team piloted eight items on attitudes to an introductory statistics course. Do the four motivation items and the four anxiety items each form a reliable scale, and do the items group into two factors as intended?
Each item uses a five-point agreement scale (1 = strongly disagree, 5 = strongly agree), an ordinal measurement treated as approximately interval, which is common practice for five or more categories.
| Item | Wording (fictional) | Intended scale | Reverse worded? |
|---|---|---|---|
| mot1 | I enjoy working on statistics problems | Motivation | No |
| mot2 | I want to do well in this course | Motivation | No |
| mot3 | I study statistics beyond what is required | Motivation | No |
| mot4r | Statistics is pointless for my degree | Motivation | Yes: score as mot4 = 6 - mot4r |
| anx1 | I feel nervous before a statistics quiz | Anxiety | No |
| anx2 | My mind goes blank when I see formulas | Anxiety | No |
| anx3 | I worry about failing this course | Anxiety | No |
| anx4 | I avoid asking questions in tutorials | Anxiety | No |
The 40 responses (rows are students, columns in the order mot1, mot2, mot3, mot4r, anx1, anx2, anx3, anx4):
| Students | Responses |
|---|---|
| 1-4 | 2 3 1 5 2 3 4 2 / 3 3 4 2 3 4 4 3 / 2 2 3 4 3 2 3 3 / 5 4 5 2 3 5 5 2 |
| 5-8 | 3 3 4 2 2 2 2 3 / 3 3 2 3 3 3 2 3 / 4 4 3 3 4 4 5 3 / 2 3 2 2 1 1 2 2 |
| 9-12 | 3 4 2 4 5 4 3 3 / 3 2 3 3 3 3 3 1 / 4 4 5 2 4 5 3 3 / 2 3 5 1 1 2 2 1 |
| 13-16 | 5 5 3 1 3 3 3 1 / 2 2 3 3 4 2 2 3 / 4 2 2 4 4 4 5 3 / 3 4 3 2 1 2 3 1 |
| 17-20 | 3 3 3 3 3 4 1 4 / 4 3 3 4 3 3 3 1 / 5 4 3 3 4 2 4 3 / 4 4 5 2 2 2 2 3 |
| 21-24 | 3 4 5 3 3 5 5 5 / 5 5 5 2 2 3 2 3 / 5 2 5 2 2 4 5 3 / 4 4 3 3 2 1 2 2 |
| 25-28 | 2 3 3 3 4 4 4 3 / 2 1 3 5 2 3 4 2 / 1 1 1 5 4 5 4 3 / 4 2 3 3 5 3 4 2 |
| 29-32 | 3 4 5 4 2 2 2 3 / 5 5 4 2 1 1 2 1 / 2 2 3 3 1 2 3 2 / 4 2 2 3 2 2 2 2 |
| 33-36 | 1 3 2 4 3 5 2 3 / 5 2 3 2 2 1 3 1 / 5 4 3 3 4 4 5 3 / 1 2 3 4 4 5 3 3 |
| 37-40 | 5 5 5 2 3 3 4 4 / 1 3 2 4 2 3 2 3 / 1 2 2 3 2 3 3 2 / 2 3 4 4 4 3 4 3 |
Assumptions and how to check each
| Assumption | Check | R | Python | What to do if violated |
|---|---|---|---|---|
| Reverse-worded items are recoded | Item correlates negatively with the rest of its scale | cor(d); recode with 6 - x on a 1-5 scale | d.corr(); 6 - d[col] | Recode, then recompute everything |
| Each scale is unidimensional (for alpha) | One dominant eigenvalue within the scale; one-factor EFA fits | eigen(cor(scale))$values | np.linalg.eigvalsh(np.corrcoef(scale.T)) | Split the scale or drop items that belong elsewhere |
| Items measure the construct about equally (tau-equivalence, for alpha) | One-factor loadings similar in size | factanal(scale, 1)$loadings | Factor(scale, 1, method="ml") | Report omega, which allows unequal loadings |
| Errors are uncorrelated | Pairs of items with very similar wording or a shared method | Residual correlations after the factor model | Same | Rewrite items; model correlated errors in CFA |
| Correlations are worth factoring | Several correlations above about 0.3; no item uncorrelated with all others | round(cor(X), 2) | X.corr().round(2) | Drop isolated items; reconsider the item pool |
| Enough respondents | n and n per item; stable loadings across random halves | nrow(d) | len(d) | Collect more data; describe results as exploratory |
| Approximately interval items, not badly skewed | Item frequency tables | table(d$mot1) | d["mot1"].value_counts() | Polychoric correlations (R psych), or ordinal CFA |
How it works
Plain language first. If four items all measure motivation, students who are more motivated should tend to score higher on all four, so the items correlate. When you add the items, the shared part (motivation) adds up faster than the item-specific noise, because noise in different items partly cancels. Alpha compares the variance of the total score with the sum of the item variances: if the items move together, the total varies much more than the parts alone would suggest, and alpha is high.
Cronbach's alpha. For items with variances and total score variance :
Alpha rises with the average inter-item correlation and with the number of items. It is a lower bound on reliability when items are unidimensional with unequal loadings, and it is not a test of unidimensionality: a two-factor set of many items can still give a high alpha.
Alpha if item deleted and item-rest correlation. Recompute alpha leaving each item out; if alpha rises clearly when an item is removed, that item adds more noise than signal. The item-rest correlation (also called corrected item-total correlation) correlates each item with the sum of the other items in its scale; values below about 0.3 flag weak items.
McDonald's omega. From a one-factor model of the scale with standardised loadings and uniquenesses :
Omega equals alpha when all loadings are equal and is usually a little higher otherwise.
PCA versus EFA. PCA finds weighted sums of the standardised items, , that keep as much total variance as possible; the weights are the eigenvectors of the correlation matrix , and each eigenvalue is the variance its component keeps. EFA instead assumes a model,
where each item is a combination of a few latent factors plus a unique part . The loadings matrix describes only the shared (common) variance; holds the uniquenesses. The communality of an item, , is the share of its variance explained by the factors. Use PCA for data reduction; use EFA when you are asking about constructs.
How many factors. Kaiser's rule keeps eigenvalues above 1 (simple, but tends to keep too many with many items and can flip on a value like 0.99). The scree plot keeps the factors before the "elbow". Parallel analysis (Horn 1965) compares each eigenvalue with the eigenvalues from random data of the same size, and keeps factors whose eigenvalue beats the random one (here, the 95th percentile of 1,000 simulations). Parallel analysis is the most defensible of the three; theory and interpretability have the final say.
Rotation. A factor solution can be rotated without changing its fit. Varimax (orthogonal) keeps factors uncorrelated and makes each column of loadings as "simple" as possible. Oblique rotations (oblimin, promax) let factors correlate, which is more realistic for psychological constructs; they report a factor correlation matrix . If the oblique factor correlation is small (say below 0.3 in absolute value), the varimax and oblique loadings will look almost the same.
| Symbol | Meaning |
|---|---|
| Number of items in a scale | |
| , | Variance of item , variance of the total score |
| Loading of item on factor (correlation-like, between -1 and 1 for orthogonal solutions) | |
| , | Uniqueness and communality of item , with |
| Item correlation matrix | |
| Factor correlation matrix (identity for orthogonal rotation) | |
| , | Cronbach's alpha, McDonald's omega |
Worked example A (full)
Aims: (1) reverse code mot4r; (2) compute alpha and item statistics for each scale; (3) decide how many factors; (4) fit and rotate a two-factor EFA; (5) compare with PCA.
R code (base R only):
items <- matrix(c(
2,3,1,5,2,3,4,2, 3,3,4,2,3,4,4,3, 2,2,3,4,3,2,3,3, 5,4,5,2,3,5,5,2,
3,3,4,2,2,2,2,3, 3,3,2,3,3,3,2,3, 4,4,3,3,4,4,5,3, 2,3,2,2,1,1,2,2,
3,4,2,4,5,4,3,3, 3,2,3,3,3,3,3,1, 4,4,5,2,4,5,3,3, 2,3,5,1,1,2,2,1,
5,5,3,1,3,3,3,1, 2,2,3,3,4,2,2,3, 4,2,2,4,4,4,5,3, 3,4,3,2,1,2,3,1,
3,3,3,3,3,4,1,4, 4,3,3,4,3,3,3,1, 5,4,3,3,4,2,4,3, 4,4,5,2,2,2,2,3,
3,4,5,3,3,5,5,5, 5,5,5,2,2,3,2,3, 5,2,5,2,2,4,5,3, 4,4,3,3,2,1,2,2,
2,3,3,3,4,4,4,3, 2,1,3,5,2,3,4,2, 1,1,1,5,4,5,4,3, 4,2,3,3,5,3,4,2,
3,4,5,4,2,2,2,3, 5,5,4,2,1,1,2,1, 2,2,3,3,1,2,3,2, 4,2,2,3,2,2,2,2,
1,3,2,4,3,5,2,3, 5,2,3,2,2,1,3,1, 5,4,3,3,4,4,5,3, 1,2,3,4,4,5,3,3,
5,5,5,2,3,3,4,4, 1,3,2,4,2,3,2,3, 1,2,2,3,2,3,3,2, 2,3,4,4,4,3,4,3),
ncol = 8, byrow = TRUE,
dimnames = list(NULL, c("mot1","mot2","mot3","mot4r","anx1","anx2","anx3","anx4")))
d <- as.data.frame(items)
d$mot4 <- 6 - d$mot4r # reverse code (1-5 scale)
alpha <- function(x) { k <- ncol(x); k / (k - 1) * (1 - sum(apply(x, 2, var)) / var(rowSums(x))) }
mot <- d[, c("mot1","mot2","mot3","mot4")]; anx <- d[, c("anx1","anx2","anx3","anx4")]
alpha(mot); alpha(anx); alpha(d[, c("mot1","mot2","mot3","mot4r")]) # last one: forgot to reverse
item_stats <- function(x) t(sapply(names(x), function(j) c(
item_rest_r = cor(x[[j]], rowSums(x[names(x) != j])),
alpha_if_deleted = alpha(x[names(x) != j]))))
round(item_stats(mot), 3); round(item_stats(anx), 3)
omega1 <- function(x) { f <- factanal(x, factors = 1); l <- f$loadings[, 1]
sum(l)^2 / (sum(l)^2 + sum(f$uniquenesses)) }
omega1(mot); omega1(anx)
X <- d[, c("mot1","mot2","mot3","mot4","anx1","anx2","anx3","anx4")]
pc <- prcomp(X, scale. = TRUE); round(pc$sdev^2, 3) # eigenvalues
set.seed(2026) # parallel analysis
sim <- replicate(1000, eigen(cor(matrix(rnorm(40 * 8), 40, 8)))$values)
round(apply(sim, 1, quantile, 0.95), 3)
factanal(X, factors = 2, rotation = "varimax")
factanal(X, factors = 2, rotation = "promax")
Output (abridged and relabelled; R hides loadings below 0.1, shown here with print(..., cutoff = 0)):
alpha motivation: 0.8 anxiety: 0.762
alpha motivation if mot4 NOT reversed: 0.072
item_rest_r alpha_if_deleted
mot1 0.622 0.753
mot2 0.609 0.753
mot3 0.596 0.759
mot4 0.652 0.737
anx1 0.630 0.667
anx2 0.703 0.619
anx3 0.474 0.752
anx4 0.455 0.758
omega (1-factor, standardised) motivation: 0.806 anxiety: 0.772
eigenvalues: 2.767 2.221 0.988 0.673 0.456 0.413 0.273 0.209
cumulative proportion: 0.346 0.624 0.747 0.831 0.888 0.940 0.974 1.000
parallel analysis 95th percentile: 1.978 1.593 1.341 1.146 0.977 0.826 0.688 0.544
factanal(X, factors = 2, rotation = "varimax")
Uniquenesses:
mot1 mot2 mot3 mot4 anx1 anx2 anx3 anx4
0.497 0.553 0.478 0.322 0.448 0.342 0.648 0.666
Loadings:
Factor1 Factor2
mot1 0.709 0.023
mot2 0.669 0.007
mot3 0.721 0.051
mot4 0.767 -0.299
anx1 -0.130 0.732
anx2 -0.089 0.806
anx3 0.064 0.590
anx4 0.001 0.578
Factor1 Factor2
SS loadings 2.087 1.959
Proportion Var 0.261 0.245
Cumulative Var 0.261 0.506
The chi square statistic is 22.73 on 13 degrees of freedom. The p-value is 0.045
factanal(X, factors = 2, rotation = "promax")
Loadings: mot1 0.712 0.055 | mot2 0.671 0.037 | mot3 0.725 0.084 | mot4 0.757 -0.266
anx1 -0.101 0.728 | anx2 -0.057 0.804 | anx3 0.088 0.594 | anx4 0.024 0.579
Factor Correlations: Factor1 with Factor2 = -0.084
Python code (numpy, pandas and statsmodels):
import numpy as np, pandas as pd
from statsmodels.multivariate.factor import Factor
rows = [[2,3,1,5,2,3,4,2], [3,3,4,2,3,4,4,3], [2,2,3,4,3,2,3,3], [5,4,5,2,3,5,5,2],
[3,3,4,2,2,2,2,3], [3,3,2,3,3,3,2,3], [4,4,3,3,4,4,5,3], [2,3,2,2,1,1,2,2],
[3,4,2,4,5,4,3,3], [3,2,3,3,3,3,3,1], [4,4,5,2,4,5,3,3], [2,3,5,1,1,2,2,1],
[5,5,3,1,3,3,3,1], [2,2,3,3,4,2,2,3], [4,2,2,4,4,4,5,3], [3,4,3,2,1,2,3,1],
[3,3,3,3,3,4,1,4], [4,3,3,4,3,3,3,1], [5,4,3,3,4,2,4,3], [4,4,5,2,2,2,2,3],
[3,4,5,3,3,5,5,5], [5,5,5,2,2,3,2,3], [5,2,5,2,2,4,5,3], [4,4,3,3,2,1,2,2],
[2,3,3,3,4,4,4,3], [2,1,3,5,2,3,4,2], [1,1,1,5,4,5,4,3], [4,2,3,3,5,3,4,2],
[3,4,5,4,2,2,2,3], [5,5,4,2,1,1,2,1], [2,2,3,3,1,2,3,2], [4,2,2,3,2,2,2,2],
[1,3,2,4,3,5,2,3], [5,2,3,2,2,1,3,1], [5,4,3,3,4,4,5,3], [1,2,3,4,4,5,3,3],
[5,5,5,2,3,3,4,4], [1,3,2,4,2,3,2,3], [1,2,2,3,2,3,3,2], [2,3,4,4,4,3,4,3]]
d = pd.DataFrame(rows, columns=["mot1","mot2","mot3","mot4r","anx1","anx2","anx3","anx4"])
d["mot4"] = 6 - d["mot4r"]
def alpha(x):
x = np.asarray(x, float); k = x.shape[1]
return k / (k - 1) * (1 - x.var(axis=0, ddof=1).sum() / x.sum(axis=1).var(ddof=1))
mot = d[["mot1","mot2","mot3","mot4"]]; anx = d[["anx1","anx2","anx3","anx4"]]
print(alpha(mot), alpha(anx))
for sc in (mot, anx):
for j in sc.columns:
rest = sc.drop(columns=j)
print(j, np.corrcoef(sc[j], rest.sum(axis=1))[0, 1], alpha(rest))
X = d[["mot1","mot2","mot3","mot4","anx1","anx2","anx3","anx4"]]
ev = np.sort(np.linalg.eigvalsh(np.corrcoef(X.T.values)))[::-1]
rng = np.random.default_rng(2026)
sim = np.array([np.sort(np.linalg.eigvalsh(np.corrcoef(rng.standard_normal((40, 8)).T)))[::-1]
for _ in range(1000)])
print(ev, np.percentile(sim, 95, axis=0))
fa = Factor(X.values, n_factor=2, method="ml").fit()
fa.rotate("varimax")
print(fa.uniqueness, np.real(fa.loadings))
fo = Factor(X.values, n_factor=2, method="ml").fit()
fo.rotate("oblimin")
T = np.real(fo.rotation_matrix)
print(np.real(fo.loadings), (T.T @ T)[0, 1]) # factor correlation
Output (abridged, rounded and relabelled):
alpha motivation = 0.800, anxiety = 0.762
mot1: item-rest r = 0.622, alpha if deleted = 0.753 (all eight rows match R)
eigenvalues: [2.767 2.221 0.988 0.673 0.456 0.413 0.273 0.209]
parallel 95th pct: [1.979 1.59 1.346 1.152 0.987 0.831 0.679 0.529]
uniquenesses: [0.497 0.553 0.478 0.322 0.448 0.342 0.648 0.666]
varimax loadings:
[[-0.709 0.022]
[-0.669 0.006]
[-0.721 0.05 ]
[-0.767 -0.3 ]
[ 0.129 0.732]
[ 0.088 0.806]
[-0.065 0.589]
[-0.002 0.578]]
oblimin loadings:
[[-0.718 -0.08 ]
[-0.676 -0.06 ]
[-0.733 -0.109]
[-0.748 0.241]
[ 0.066 -0.729]
[ 0.019 -0.808]
[-0.117 -0.601]
[-0.053 -0.584]]
oblimin factor correlation: -0.166
Where R and Python differ, by design. The alpha values, item statistics, eigenvalues and ML uniquenesses agree
exactly. The parallel analysis thresholds differ in the third decimal because R and NumPy draw different random
numbers from the same seed. The Python factors come out with flipped signs (motivation loadings negative), and the
sign of each column can even change from one run to the next (in some runs the anxiety column is negative and the
printed factor correlation is +0.166): the sign of a factor is arbitrary, so align the columns with R or with the
item content (multiply a column, and its row and column of the factor correlation matrix, by -1) before reporting. Base R offers
varimax and promax; Python's statsmodels offers varimax, oblimin, promax and others. Promax (R) and oblimin (Python)
are both oblique but use different criteria: promax starts from the varimax solution, raises its loadings to a power
(4 in R) to build a sharper target, and rotates obliquely towards that target (Hendrickson and White 1964); direct
oblimin minimises the cross-products of squared loadings between factors without a target. So the factor correlation
differs (-0.08 versus -0.17 after aligning signs) while the pattern of loadings is the same. statsmodels 0.15 returns loadings with a zero imaginary part, hence np.real.
Calculation by hand for the key statistic. Alpha for the motivation scale. Item variances (after reverse coding) are 1.840, 1.169, 1.372 and 1.051, summing to 5.432. The variance of the motivation total is 13.587. So
Without reverse coding mot4r, alpha collapses to 0.072, because mot4r correlates negatively with the other three items and cancels them out of the total.
Scree plot and parallel analysis. Two eigenvalues are above the random-data threshold; the third (0.988) is below its threshold (1.341), and also just below 1, so Kaiser's rule and parallel analysis agree on two factors here.
PCA for comparison. The first two principal components keep 62.4% of the total variance (eigenvalues 2.767 and
2.221 out of 8). The unrotated PC1 weights (R prcomp; the overall sign is arbitrary) are positive for the motivation
items (0.34 to 0.49) and negative for the anxiety items (-0.22 to -0.37): it blends both constructs into a "positive attitude" contrast. The two-factor EFA
explains 50.6% of the item variance, less than PCA, because EFA only counts shared variance and leaves the unique
part in the uniquenesses. This is the practical difference: PCA summarises everything, EFA separates what items have
in common from what is specific to each.
Loadings table (varimax, R; loadings of at least 0.40 in bold).
| Item | Factor 1 (Motivation) | Factor 2 (Anxiety) | Communality |
|---|---|---|---|
| mot1 | 0.709 | 0.023 | 0.503 |
| mot2 | 0.669 | 0.007 | 0.447 |
| mot3 | 0.721 | 0.051 | 0.522 |
| mot4 (reversed) | 0.767 | -0.299 | 0.678 |
| anx1 | -0.130 | 0.732 | 0.552 |
| anx2 | -0.089 | 0.806 | 0.658 |
| anx3 | 0.064 | 0.590 | 0.352 |
| anx4 | 0.001 | 0.578 | 0.334 |
Effect size with CI. In reliability analysis the "effect" is the reliability coefficient. Motivation: alpha = .80, omega = .81. Anxiety: alpha = .76, omega = .77. Confidence intervals for alpha with n = 40 are wide: the Feldt (F-distribution) 95% CI is [.68, .89] for motivation and [.61, .86] for anxiety, and a percentile bootstrap over respondents (9,999 resamples, NumPy seed 2026; academic/stats-resampling-methods) gives similar intervals, [.67, .88] and [.62, .84]. Note that they are asymmetric: there is more room below alpha than above it. For the factor model, the variance explained (50.6%) and the factor correlation (-0.08 promax, -0.17 oblimin) are the summary numbers.
Interpretation. After reverse coding mot4r, both scales show acceptable internal consistency for a pilot. Deleting any item would lower alpha, so all items stay. The eight items separate cleanly into motivation and anxiety: every item loads at least 0.58 on its intended factor and no more than 0.30 in absolute value on the other. The reversed item mot4 has the largest cross-loading (-0.30 on anxiety), which makes sense: students who find statistics pointless may also be anxious about it. The two factors barely correlate, so the orthogonal and oblique solutions agree. The chi-square test of exact fit is marginally significant (p = .045), and a three-factor model would fit exactly (p = .289), but parallel analysis, Kaiser's rule and the item content all support two factors; the chi-square test is sensitive and is not a good guide on its own.
APA-style report sentence. After reverse scoring item 4, internal consistency was acceptable for motivation (4 items, α = .80, ω = .81) and anxiety (4 items, α = .76, ω = .77; n = 40). Parallel analysis supported two factors, and a maximum likelihood EFA with promax rotation reproduced the intended structure (loadings .58 to .80 on the intended factor, cross-loadings |λ| ≤ .27; factor correlation r = -.08), explaining 50.3% of the item variance.
Worked example B (half solved)
Focus on the anxiety scale (anx1 to anx4).
| Item | Item-rest r | Alpha if deleted | Varimax loading on anxiety |
|---|---|---|---|
| anx1 | 0.630 | 0.667 | 0.732 |
| anx2 | 0.703 | 0.619 | 0.806 |
| anx3 | 0.474 | 0.752 | 0.590 |
| anx4 | 0.455 | 0.758 | 0.578 |
- The full-scale alpha is 0.762. Does deleting any item raise alpha? [ ]
- Which item is the weakest, by item-rest correlation? [ ] Is it below the usual 0.3 warning level? [ ]
- Omega for the anxiety scale is 0.772, slightly above alpha. Why is omega higher? Hint: compare the loadings. [ ]
- Write the decision: "All four anxiety items were [ ] because [ ]."
- The communality of anx4 is [ ]. In words, the anxiety factor explains about [ ]% of the variance of anx4.
Exercise C (unsolved)
Five students answered a three-item "library confidence" scale for Harbour City Library workshops (1 to 5):
| Student | item1 | item2 | item3 |
|---|---|---|---|
| S1 | 4 | 5 | 4 |
| S2 | 2 | 3 | 2 |
| S3 | 3 | 3 | 4 |
| S4 | 5 | 4 | 5 |
| S5 | 1 | 2 | 2 |
- Compute the sample variance (divide by n - 1) of each item.
- Compute each student's total, then the variance of the totals.
- Compute alpha. Then check with
alpha()from Example A in R or Python. - Would you report this alpha with confidence? Give two reasons why not.
Reading software output
| Output line | Meaning | What to report |
|---|---|---|
Uniquenesses | : share of each item's variance not explained by the factors | Usually as communalities in the loadings table |
Loadings | ; for orthogonal rotation, the correlation of item and factor | Yes, full table, with a stated cut-off for bold |
| Blank cells in R's printed loadings | Values below 0.1 hidden by default (cutoff = 0 shows all) | Report all values or state the cut-off |
SS loadings | Sum of squared loadings per factor (variance explained by the factor) | Yes, with Proportion Var |
Proportion Var, Cumulative Var | Share of total item variance explained | Yes |
Factor Correlations (promax) or (oblimin) | Correlation between oblique factors | Yes, for oblique rotations |
The chi square statistic is 22.73 on 13 degrees of freedom | Test of exact fit of the k-factor model; sensitive to n | Optional; do not choose k on this alone |
prcomp sdev | Square roots of the eigenvalues | Eigenvalues (square them), for the scree plot |
statsmodels loadings with +0.j | Complex dtype artefact; the imaginary part is zero | Take np.real |
Reporting template
Fill-in sentences.
- Reliability: "After reverse scoring [items], internal consistency was [acceptable / good] for [scale 1] ([k] items, α = [ ], ω = [ ]) and [scale 2] ([k] items, α = [ ], ω = [ ]), n = [n]."
- EFA: "[Parallel analysis / scree / theory] supported [k] factors. A [maximum likelihood / principal axis] EFA with [promax / oblimin / varimax] rotation explained [ ]% of the item variance; all items loaded at least [ ] on their intended factor, with cross-loadings below [ ] (factor correlation r = [ ]). [Any item dropped and why.]"
- Next step: "The structure will be tested by CFA on [independent sample]."
| Scale | Items | Reversed | α | ω | Lowest item-rest r | Decision |
|---|---|---|---|---|---|---|
| Example: Motivation | mot1-mot4 | mot4 | .80 | .81 | .60 (mot3) | Keep all items |
| Example: Anxiety | anx1-anx4 | none | .76 | .77 | .46 (anx4) | Keep all items |
| [ ] | [ ] | [ ] | [ ] | [ ] | [ ] | [ ] |
Results checklist.
- Reverse-coded items are named and were recoded before any analysis.
- Alpha (and preferably omega) is reported per scale, never for all items pooled across scales.
- The number of factors is justified by parallel analysis or a stated rule, plus content.
- Extraction method, rotation and the full loadings table (with communalities) are reported.
- Factor correlations are reported for oblique rotations.
- Any dropped item is listed with the reason.
- Results are labelled exploratory, and CFA on new data is planned or reported.
Common mistakes and misconceptions
- Forgetting to reverse code. In Example A, alpha drops from 0.80 to 0.07 when mot4r is left as it is. A negative item-rest correlation is the usual sign.
- "High alpha means the scale is unidimensional." It does not. Alpha grows with the number of items; twenty items from two unrelated factors can give alpha above 0.8. Check dimensionality with EFA.
- "Alpha above 0.7 means the scale is valid." Reliability is about consistency, not about measuring the right thing. A scale can reliably measure the wrong construct.
- Chasing alpha by deleting items. Removing items to push alpha up can narrow the construct and capitalises on chance in small samples. Decide with content and loadings, not alpha alone.
- Calling PCA "factor analysis". PCA components include unique and error variance; they are data summaries. Loadings are larger and variance explained is higher than in EFA, which can mislead.
- Kaiser's rule as the only criterion. It over-extracts with many items and flips on eigenvalues near 1 (0.988 here). Use parallel analysis.
- Varimax by default. If constructs are expected to correlate, start with an oblique rotation; switch to varimax only if factor correlations are small.
- Reading a sign flip as a finding. Factor signs are arbitrary; Python's negative motivation loadings mean the same as R's positive ones.
- Running EFA and CFA on the same data and calling it confirmation. CFA on the same sample only confirms what was fitted. Use a new sample or a pre-registered split.
Self-test questions
- A five-item scale has alpha = 0.45, and one item has an item-rest correlation of -0.38. What is the most likely explanation, and what do you check first?
- In one sentence each: what does PCA do, and what does EFA assume?
- Eigenvalues are 3.1, 1.4, 1.05, 0.8 and parallel analysis thresholds are 1.6, 1.3, 1.15, 1.05. How many factors do Kaiser's rule and parallel analysis suggest?
- An oblique rotation gives a factor correlation of 0.55. Should you report the varimax solution instead? Why?
- Alpha is 0.92 for a 30-item scale. Name two reasons this does not prove the scale measures one construct.
- An item loads 0.45 on Factor 1 and 0.42 on Factor 2. What do you call this and what might you do?
My notes and next steps
| Item | Your entry |
|---|---|
| Confidence with this method (1 to 5) | [ ] |
| What I can now do without notes | [ ] |
| Open questions (for example omega hierarchical, ordinal data) | [ ] |
| Mistakes to copy to my error log (academic/stats-error-log) | [ ] |
| Next review date (spacing: 2 days, 1 week, 3 weeks) | YYYY-MM-DD |
| Next step for my instrument (CFA sample, item rewrite) | [ ] |
Sources and further reading
Structure aligned with common psychometric reporting practice (reverse coding, reliability per scale, retention method, extraction and rotation, loadings table); content based on the original method papers, written in our own words.
- Cronbach, L. J. (1951). Coefficient alpha and the internal structure of tests. Psychometrika, 16(3), 297–334.
- Feldt, L. S. (1965). The approximate sampling distribution of Kuder-Richardson reliability coefficient twenty. Psychometrika, 30(3), 357–370.
- McDonald, R. P. (1999). Test Theory: A Unified Treatment. Lawrence Erlbaum.
- Kaiser, H. F. (1958). The varimax criterion for analytic rotation in factor analysis. Psychometrika, 23(3), 187–200.
- Kaiser, H. F. (1960). The application of electronic computers to factor analysis. Educational and Psychological Measurement, 20(1), 141–151.
- Cattell, R. B. (1966). The scree test for the number of factors. Multivariate Behavioral Research, 1(2), 245–276.
- Horn, J. L. (1965). A rationale and test for the number of factors in factor analysis. Psychometrika, 30(2), 179–185.
- Hendrickson, A. E., and White, P. O. (1964). Promax: a quick method for rotation to oblique simple structure. British Journal of Statistical Psychology, 17(1), 65–70.
- Fabrigar, L. R., Wegener, D. T., MacCallum, R. C., and Strahan, E. J. (1999). Evaluating the use of exploratory factor analysis in psychological research. Psychological Methods, 4(3), 272–299.
- Sijtsma, K. (2009). On the use, the misuse, and the very limited usefulness of Cronbach's alpha. Psychometrika, 74(1), 107–120.
- NIST/SEMATECH e-Handbook of Statistical Methods, section 6.5.5 Principal Components, https://www.itl.nist.gov/div898/handbook/ (accessed 2026-10-25). Public domain.
- R documentation for
factanal,prcompandvarimax/promax; statsmodels documentation forstatsmodels.multivariate.factor.Factor. For CFA: Rlavaanand Pythonsemopydocumentation. - Further reading: de Smith, M. J., Statistical Analysis Handbook (2024 edition, statsref.com); OpenIntro Statistics (CC BY-SA).
Answer key
Example B.
- No. Every alpha-if-deleted value (0.667, 0.619, 0.752, 0.758) is below 0.762.
- anx4 (0.455), followed closely by anx3 (0.474). Neither is below 0.3.
- The loadings are unequal (0.58 to 0.81). Alpha assumes equal loadings and is then a lower bound; omega uses the actual loadings, so it is a little higher (0.772 versus 0.762).
- "All four anxiety items were retained because no deletion would raise alpha and every item loaded at least 0.58 on the anxiety factor."
- 0.334; about 33%.
Exercise C.
- Item variances: item1 = 2.5, item2 = 1.3, item3 = 1.8 (sum 5.6).
- Totals 13, 7, 10, 14, 5; variance of totals = 14.7.
- .
- Only five respondents, so the estimate is extremely unstable (a confidence interval would be very wide); only three items, so unidimensionality cannot be checked meaningfully; and a high alpha says nothing about validity.
Self-test.
- An item was not reverse coded (or is miscoded). Check its wording and its correlations with the other items, recode it, and recompute.
- PCA finds weighted sums of the variables that keep as much total variance as possible. EFA assumes each item is driven by a few latent factors plus unique variance, and models only the shared variance.
- Kaiser: 3 (3.1, 1.4 and 1.05 are above 1). Parallel analysis: 2 (3.1 > 1.6 and 1.4 > 1.3, but 1.05 < 1.15).
- No. A correlation of 0.55 is substantial; forcing orthogonal factors would distort the loadings. Report the oblique pattern loadings and the factor correlation.
- Alpha rises with the number of items, so 30 items can give a high alpha even with two or more factors; and alpha assumes rather than tests unidimensionality. Check with EFA or CFA.
- A cross-loading (complex item). Check the wording for double meaning; consider rewriting or dropping it, or keep it only if theory says it reflects both constructs.
Revision history
| Version | Date | Author | Change |
|---|---|---|---|
| 0.1 | YYYY-MM-DD | [Your name] | First version from the template |
| [ ] | YYYY-MM-DD | [ ] | [ ] |
관련 템플릿
Statistical Analysis Plan Template (Statistics, Thesis or Project)
Statistical analysis plan for a thesis or project: estimands, hypotheses, sample size, primary model, pre-set assumption fallbacks, missing data, multiplicity, sensitivity, deviations log
학술Statistical Analysis Report Template (Statistics, Thesis or Client)
Complete statistical analysis report for a thesis results chapter or client: plain-language summary, methods, descriptives, main analyses, assumption checks, sensitivity, limitations, reproducibility appendix, reviewer checklist
학술Finance Case Analysis Template (Case Method, Teaching Note)
Decision maker and question, situation and issue diagnosis, WACC and NPV/IRR analysis, valuation, alternatives scoring, recommendation, implementation, teaching note