Executive Summary
Reliability of a 6-item scale
Across 6 items and 200 responses, Cronbach's alpha is 0.776 (95% CI 0.724–0.821)—acceptable internal consistency. Standardized alpha is 0.786; mean inter-item correlation is 0.38. However, Parking Satisfaction is weak: its corrected item-total correlation is −0.078 (below the 0.30 threshold) and removing it raises alpha to 0.882. This item is actively hurting scale reliability and should be considered for deletion. The remaining 5 items show item-total correlations ranging from 0.659 to 0.706, indicating they cohere well.
Analysis Overview
Internal consistency of a 6-item scale across 200 complete responses.
Cronbach's alpha measures internal consistency—whether the 6 items move together enough to justify summing them into a single scale score. The coefficient ranges from 0 to 1; this scale achieves 0.776, landing in the acceptable band (0.7–0.8). The standardized alpha of 0.786 rescales items to equal variance; the small gap (0.010) from raw alpha indicates items have comparable spreads. Critically, an alpha above 0.95 signals redundant near-duplicate items, not improved measurement. Because alpha rises mechanically with each added item, the per-item analysis—especially alpha-if-deleted and item-total correlations—matters as much as the headline number for determining whether the scale is truly reliable.
Data Quality
Items used, items dropped, and complete responses retained.
All 200 rows loaded into analysis with no missing data: 200 complete responses across 6 items, 0 rows removed, 0 items dropped. Cronbach's alpha requires listwise completeness—every respondent must answer every item—so the full dataset entered the calculation. Data quality is clean; no non-numeric or constant items required exclusion. This clean input supports confidence in the reliability estimates without qualification for missing-data patterns.
Item Analysis
Per-item mean, spread, item-total correlation, and alpha-if-deleted.
| Item | Mean | SD | Item Total Correlation | Alpha If Deleted |
|---|---|---|---|---|
| Enjoy My Work | 4.03 | 1.22 | 0.697 | 0.697 |
| Proud Of Company | 4.93 | 1.15 | 0.659 | 0.71 |
| Recommend Employer | 4.01 | 1.14 | 0.706 | 0.698 |
| Look Forward To Work | 5.02 | 1.22 | 0.666 | 0.705 |
| Feel Valued | 3.98 | 1.29 | 0.669 | 0.702 |
| Parking Satisfaction | 3.98 | 1.31 | -0.078 | 0.882 |
Five items show strong coherence with corrected item-total correlations from 0.659 to 0.706: Enjoy My Work (0.697), Recommend Employer (0.706), Look Forward To Work (0.666), Feel Valued (0.669), and Proud Of Company (0.659). Parking Satisfaction is an outlier with −0.078, indicating it does not track the underlying construct the other items measure. Its mean (3.98) and standard deviation (1.31) are comparable to other items, so the weakness is not a scale-of-measurement artifact. The negative correlation suggests possible reverse-scoring error or genuine measurement of a different construct. Removing Parking Satisfaction would yield alpha 0.882, a substantial gain from the current 0.776.
Alpha If Item Removed
The scale's reliability with each item dropped, versus the overall alpha.
One item sits above the overall alpha line of 0.776: Parking Satisfaction (0.882 without it). All other items sit below, meaning removing them would lower reliability. The next highest alpha-if-deleted is Proud Of Company at 0.71, still well below baseline. The Parking Satisfaction result is unambiguous: this item is the single most improving cut, lifting alpha by 0.106 points. The remaining five items form a cohesive cluster (alpha-if-deleted ranging 0.697–0.71), each contributing positively to scale reliability. This pattern strongly supports dropping Parking Satisfaction to improve the scale.
Inter-Item Correlation Summary
Alpha, standardized alpha, inter-item correlation range, and confidence interval.
| Statistic | Value | Interpretation |
|---|---|---|
| Items in scale | 6 | Number of items summed into the scale. |
| Complete responses | 200 | Respondents with a value on every item (listwise complete). |
| Mean inter-item correlation | 0.380 | Average correlation among item pairs — the engine of internal consistency. |
| Lowest inter-item correlation | -0.091 | Weakest pairwise item relationship. |
| Highest inter-item correlation | 0.668 | Strongest pairwise item relationship. |
| Cronbach's alpha (raw) | 0.776 | Internal consistency: acceptable. |
| Standardized alpha | 0.786 | Alpha rescaled as if every item had equal variance — compare to raw. |
| Alpha 95% CI (Feldt) | 0.724 to 0.821 | Range the true alpha plausibly falls in. |
Inter-item correlations range from −0.091 to 0.668, with a mean of 0.38—within the healthy 0.15–0.50 band that indicates shared construct without redundancy. The Parking Satisfaction item drives the negative floor (−0.091 is its correlation with at least one other item), confirming its misalignment. Raw (0.776) and standardized (0.786) alpha are nearly identical, showing items operate on comparable scales. The Feldt 95% confidence interval (0.724–0.821) anchors the true population alpha in the acceptable range. These statistics together establish that the scale's reliability rests on moderate, healthy inter-item relationships—except for Parking Satisfaction's isolation.
Methodology
Statistical methodology and diagnostics for Scale Reliability — Cronbach's Alpha
Statistical Method
Standard-library analysis: are a set of survey or test items consistent enough to be summed into a single scale? Map three or more Likert or scale items and get Cronbach's alpha with its interpretation band and a 95% confidence interval, the standardized alpha from the mean inter-item correlation, a full item analysis (each item's mean, spread, corrected item-total correlation, and the alpha you would get if that item were removed), and the inter-item correlation summary. Built for survey validation: it tells you whether your scale holds together and which item to cut if it does not.
- The mapped items are meant to measure the same underlying construct
- Items are numeric or cleanly convertible (Likert, rating, or scale scores)
- Items are scored in a consistent direction — reverse-worded items should be recoded before analysis (a negative item-total correlation flags any that were not)
- Cronbach's alpha assumes the items are roughly unidimensional; a multi-factor set can produce a misleading single alpha
- Alpha rises mechanically with more items, so a long scale can look reliable even with modest item quality
- An alpha above 0.95 often signals redundant items rather than a better scale
- Rows with any missing item are dropped (listwise); they are counted and reported
Analysis Code
Complete R source code for this analysis
Scale Reliability — Cronbach's Alpha
Are a set of survey or test items internally consistent enough to be summed into a single scale? From the wide-format item columns the user maps, this computes Cronbach's alpha with its interpretation band and a Feldt 95% confidence interval, the standardized alpha from the mean inter-item correlation, a full item analysis (mean, spread, corrected item-total correlation, and alpha-if-item-deleted per item), and an inter-item correlation summary.
Why This Method?
Cronbach's alpha is the dominant survey-validation statistic: one number that says whether questions meant to measure the same thing actually hang together. Reporting the item-total correlations and alpha-if-deleted at the same time answers the perennial follow-up — WHICH item to cut when a scale is weak.
What This Analysis Covers
- Cronbach's alpha with interpretation band and confidence interval
- Standardized alpha from the mean inter-item correlation
- Per-item corrected item-total correlation and alpha-if-deleted
- Inter-item correlation summary (mean, min, max)
Standard Library
Platform standard-library module (LAT-1441): runs on ANY dataset via the semantic mapping {item_1..item_N}. All narrative is derived from the user's own column names and computed values.
suppressPackageStartupMessages(library(DT))
suppressPackageStartupMessages(library(htmlwidgets))
suppressPackageStartupMessages(library(arrow))
suppressPackageStartupMessages(library(knitr))
suppressPackageStartupMessages(library(rmarkdown))
suppressPackageStartupMessages(library(dplyr))
suppressPackageStartupMessages(library(tidyr))
suppressPackageStartupMessages(library(ggplot2))
suppressPackageStartupMessages(library(stringr))
suppressPackageStartupMessages(library(lubridate))
suppressPackageStartupMessages(library(broom))
suppressPackageStartupMessages(library(Matrix))
suppressPackageStartupMessages(library(cluster))
suppressPackageStartupMessages(library(data.table))Core Analysis Pipeline
compute_shared <- function(df, params, col_map = list()) {
# === SHARED EXPORTS ===
# initial_rows/final_rows/rows_removed $ row accounting (responses)
# item_names $ named character — semantic -> humanized item names
# used_items $ character — semantic item names used
# dropped_items $ character — excluded items
# dropped_note $ humanized description of drops
# n_incomplete $ responses removed by listwise deletion
# k $ integer — items in the scale
# alpha_raw / alpha_std $ numeric — Cronbach's alpha, standardized alpha
# alpha_ci $ numeric(2) or NULL — Feldt 95% CI
# band $ interpretation band for alpha_raw
# redundancy $ logical — alpha > 0.95
# rbar / r_min / r_max $ inter-item correlation summary
# item_stats_df $ data.frame(item, mean, sd, item_total_correlation, alpha_if_deleted)
# aid_df $ data.frame(item, alpha_if_deleted) — sorted, for the bar
# inter_item_summary_df $ data.frame(statistic, value, interpretation)
# worst_item_name / alpha_del_best / improves $ best single deletion
# low_itc_name $ item with the lowest corrected item-total correlation
# weak_items $ character — items with item-total correlation < 0.30
# metrics / json_output
# === /SHARED EXPORTS ===Step 1: Discover mapped items
initial_rows <- nrow(df)
item_cols <- grep("^item_[0-9]+$", names(df), value = TRUE)
item_cols <- item_cols[order(as.integer(sub("^item_", "", item_cols)))]
if (length(item_cols) < 3) {
stop("Scale reliability needs at least three items mapped(item_1, item_2, item_3). Cronbach's alpha is undefined for fewer.")
}
item_names <- setNames(humanize_semantic(item_cols, col_map), item_cols)Step 2: Coerce numeric (95% rule); drop non-numeric items (report)
dropped_items <- character(0)
dropped_reasons <- character(0)
for (ic in item_cols) {
v <- df[[ic]]
if (!is.numeric(v)) {
conv <- suppressWarnings(as.numeric(as.character(v)))
n_orig <- sum(!is.na(v) & as.character(v) != "")
if (n_orig > 0 && sum(!is.na(conv)) >= 0.95 * n_orig) {
df[[ic]] <- conv
} else {
dropped_items <- c(dropped_items, ic)
dropped_reasons <- c(dropped_reasons, "non-numeric")
next
}
}
}
usable_items <- setdiff(item_cols, dropped_items)
if (length(usable_items) < 3) {
stop(sprintf("Only %d numeric items remained after dropping non-numeric columns — need at least three to assess scale reliability.",
length(usable_items)))
}Step 3: Listwise-complete responses for the item set (report dropped)
M <- df[, usable_items, drop = FALSE]
complete_idx <- stats::complete.cases(M)
n_incomplete <- sum(!complete_idx)
M <- M[complete_idx, , drop = FALSE]Step 4: Drop constant (zero-variance) items — report them
const_items <- usable_items[vapply(usable_items, function(ic) {
vv <- M[[ic]]
is.na(var(vv)) || isTRUE(var(vv) == 0)
}, logical(1))]
if (length(const_items) > 0) {
dropped_items <- c(dropped_items, const_items)
dropped_reasons <- c(dropped_reasons, rep("constant", length(const_items)))
usable_items <- setdiff(usable_items, const_items)
M <- M[, usable_items, drop = FALSE]
}
k <- length(usable_items)
if (k < 3) {
stop(sprintf("Only %d usable items after removing non-numeric and constant columns — need at least three for Cronbach's alpha.", k))
}
final_rows <- nrow(M)
rows_removed <- initial_rows - final_rows
if (final_rows < 10) {
stop(sprintf("Only %d complete responses(no missing item) — need at least 10 to estimate Cronbach's alpha.", final_rows))
}Step 5: Cronbach's alpha
X <- as.matrix(M)
item_vars <- apply(X, 2, var)
total <- rowSums(X)
var_total <- var(total)
if (is.na(var_total) || var_total <= 0) {
stop("The total scale score has no variance — reliability cannot be estimated.")
}
alpha_raw <- (k / (k - 1)) * (1 - sum(item_vars) / var_total)Step 6: Inter-item correlation matrix -> standardized alpha
C <- suppressWarnings(cor(X))
offdiag <- C[upper.tri(C)]
offdiag <- offdiag[is.finite(offdiag)]
rbar <- if (length(offdiag) > 0) mean(offdiag) else NA_real_
r_min <- if (length(offdiag) > 0) min(offdiag) else NA_real_
r_max <- if (length(offdiag) > 0) max(offdiag) else NA_real_
alpha_std <- if (!is.na(rbar)) (k * rbar) / (1 + (k - 1) * rbar) else NA_real_Step 7: Per-item statistics — corrected item-total and alpha-if-deleted
item_mean <- colMeans(X)
item_sd <- apply(X, 2, sd)
item_total_cor <- rep(NA_real_, k)
alpha_del <- rep(NA_real_, k)
for (i in seq_len(k)) {
others <- rowSums(X[, -i, drop = FALSE])
if (!is.na(var(others)) && var(others) > 0) {
item_total_cor[i] <- suppressWarnings(cor(X[, i], others))
}
ki <- k - 1
if (ki >= 2) {
iv <- item_vars[-i]
var_i <- var(others)
if (!is.na(var_i) && var_i > 0) {
alpha_del[i] <- (ki / (ki - 1)) * (1 - sum(iv) / var_i)
}
}
}Step 8: Feldt (1965) F-based 95% CI for alpha (graceful on failure)
alpha_ci <- tryCatch({
df1 <- final_rows - 1
df2 <- (final_rows - 1) * (k - 1)
a2 <- 1 - 0.95
fL <- qf(1 - a2 / 2, df1, df2)
fU <- qf(a2 / 2, df1, df2)
lo <- 1 - (1 - alpha_raw) * fL
hi <- 1 - (1 - alpha_raw) * fU
if (is.finite(lo) && is.finite(hi)) c(lo, hi) else NULL
}, error = function(e) NULL)Step 9: Interpretation band + redundancy caveat
alpha_band <- function(a) {
if (is.na(a)) return("not estimable")
if (a < 0.5) "unacceptable"
else if (a < 0.6) "poor"
else if (a < 0.7) "questionable"
else if (a < 0.8) "acceptable"
else if (a < 0.9) "good"
else "excellent"
}
band <- alpha_band(alpha_raw)
redundancy <- !is.na(alpha_raw) && alpha_raw > 0.95
hn <- unname(item_names[usable_items])Step 10: Assemble item tables (NA-safe extremes)
item_stats_df <- data.frame(
item = hn,
mean = round(item_mean, 2),
sd = round(item_sd, 2),
item_total_correlation = round(item_total_cor, 3),
alpha_if_deleted = round(alpha_del, 3),
stringsAsFactors = FALSE
)
rownames(item_stats_df) <- NULL
weak_mask <- !is.na(item_stats_df$item_total_correlation) &
item_stats_df$item_total_correlation < 0.30
weak_items <- item_stats_df$item[weak_mask]
aid_df <- data.frame(item = hn, alpha_if_deleted = round(alpha_del, 3),
stringsAsFactors = FALSE)
aid_df <- aid_df[order(-aid_df$alpha_if_deleted, na.last = TRUE), , drop = FALSE]
rownames(aid_df) <- NULLBest single deletion — NEVER which.max over an all-NA vector
ok_del <- which(!is.na(alpha_del))
if (length(ok_del) > 0) {
best_i <- ok_del[which.max(alpha_del[ok_del])]
worst_item_name <- hn[best_i]
alpha_del_best <- alpha_del[best_i]
improves <- !is.na(alpha_del_best) && alpha_del_best > alpha_raw
} else {
worst_item_name <- NA_character_; alpha_del_best <- NA_real_; improves <- FALSE
}
ok_itc <- which(!is.na(item_total_cor))
low_itc_name <- if (length(ok_itc) > 0) hn[ok_itc[which.min(item_total_cor[ok_itc])]] else NA_character_
ci_txt <- if (!is.null(alpha_ci)) sprintf("%.3f to %.3f", alpha_ci[1], alpha_ci[2]) else "not computable for this data"
inter_item_summary_df <- data.frame(
statistic = c("Items in scale", "Complete responses",
"Mean inter-item correlation", "Lowest inter-item correlation",
"Highest inter-item correlation", "Cronbach's alpha (raw)",
"Standardized alpha", "Alpha 95% CI(Feldt)"),
value = c(
format(k, big.mark = ","),
format(final_rows, big.mark = ","),
if (is.na(rbar)) "n/a" else sprintf("%.3f", rbar),
if (is.na(r_min)) "n/a" else sprintf("%.3f", r_min),
if (is.na(r_max)) "n/a" else sprintf("%.3f", r_max),
sprintf("%.3f", alpha_raw),
if (is.na(alpha_std)) "n/a" else sprintf("%.3f", alpha_std),
ci_txt
),
interpretation = c(
"Number of items summed into the scale.",
"Respondents with a value on every item(listwise complete).",
"Average correlation among item pairs — the engine of internal consistency.",
"Weakest pairwise item relationship.",
"Strongest pairwise item relationship.",
paste0("Internal consistency: ", band, "."),
"Alpha rescaled as if every item had equal variance — compare to raw.",
"Range the true alpha plausibly falls in."
),
stringsAsFactors = FALSE
)
dropped_note <- if (length(dropped_items) > 0) {
parts <- character(0)
nn <- sum(dropped_reasons == "non-numeric")
nc <- sum(dropped_reasons == "constant")
if (nn > 0) parts <- c(parts, sprintf("%d non-numeric", nn))
if (nc > 0) parts <- c(parts, sprintf("%d constant", nc))
dn <- humanize_semantic(dropped_items, col_map)
paste0(length(dropped_items), " mapped item",
if (length(dropped_items) == 1) "" else "s", " dropped(",
paste(parts, collapse = ", "), "): ", paste(dn, collapse = ", "), ". ")
} else "All mapped items were usable. "
metrics <- list(
`Items` = k,
`Responses` = final_rows,
`Cronbachs Alpha` = round(alpha_raw, 3),
`Reliability` = band,
`Standardized Alpha`= if (is.na(alpha_std)) NA_real_ else round(alpha_std, 3),
`Mean Inter-Item r` = if (is.na(rbar)) NA_real_ else round(rbar, 3)
)
improve_answer <- if (isTRUE(improves)) {
paste0("Dropping ", worst_item_name, " would raise alpha to ",
round(alpha_del_best, 3), ".")
} else {
"No single item's removal would raise alpha."
}
json_output <- list(
answer = paste0(
"Cronbach's alpha across ", k, " items and ", format(final_rows, big.mark = ","),
" complete responses is ", round(alpha_raw, 3), " — ", band,
" internal consistency",
if (!is.null(alpha_ci)) paste0(" (95% CI ", ci_txt, ")") else "", ". ",
"The standardized alpha is ",
if (is.na(alpha_std)) "not estimable" else round(alpha_std, 3),
" and the mean inter-item correlation is ",
if (is.na(rbar)) "not estimable" else round(rbar, 3), ". ",
improve_answer,
if (redundancy) " Alpha above 0.95 may signal redundant, near-duplicate items." else ""
),
cards = lapply(
c("tldr", "overview", "preprocessing", "item_statistics",
"alpha_if_deleted", "inter_item"),
function(cid) list(id = cid, metrics = metrics)
)
)
list(
initial_rows = initial_rows, final_rows = final_rows,
rows_removed = rows_removed, n_incomplete = n_incomplete,
item_names = item_names, used_items = usable_items,
dropped_items = dropped_items, dropped_reasons = dropped_reasons,
dropped_note = dropped_note,
k = k, alpha_raw = alpha_raw, alpha_std = alpha_std, alpha_ci = alpha_ci,
ci_txt = ci_txt, band = band, redundancy = redundancy,
rbar = rbar, r_min = r_min, r_max = r_max,
item_stats_df = item_stats_df, aid_df = aid_df,
inter_item_summary_df = inter_item_summary_df,
weak_items = weak_items,
worst_item_name = worst_item_name, alpha_del_best = alpha_del_best,
improves = improves, low_itc_name = low_itc_name,
metrics = metrics, json_output = json_output
)
}