|
| 1 | +struct CronbachAlpha{T <: Real} |
| 2 | + alpha::T |
| 3 | + dropped::Vector{T} |
| 4 | +end |
| 5 | + |
| 6 | +function Base.show(io::IO, x::CronbachAlpha) |
| 7 | + @printf(io, "Cronbach's alpha for all items: %.4f\n", x.alpha) |
| 8 | + isempty(x.dropped) && return |
| 9 | + println(io, "\nCronbach's alpha if an item is dropped:") |
| 10 | + for (idx, val) in enumerate(x.dropped) |
| 11 | + @printf(io, "item %i: %.4f\n", idx, val) |
| 12 | + end |
| 13 | +end |
| 14 | + |
| 15 | +""" |
| 16 | + cronbachalpha(covmatrix::AbstractMatrix{<:Real}) |
| 17 | +
|
| 18 | +Calculate Cronbach's alpha (1951) from a covariance matrix `covmatrix` according to |
| 19 | +the [formula](https://en.wikipedia.org/wiki/Cronbach%27s_alpha): |
| 20 | +
|
| 21 | +```math |
| 22 | +\\rho = \\frac{k}{k-1} (1 - \\frac{\\sum^k_{i=1} \\sigma^2_i}{\\sum_{i=1}^k \\sum_{j=1}^k \\sigma_{ij}}) |
| 23 | +``` |
| 24 | +
|
| 25 | +where ``k`` is the number of items, i.e. columns, ``\\sigma_i^2`` the item variance, |
| 26 | +and ``\\sigma_{ij}`` the inter-item covariance. |
| 27 | +
|
| 28 | +Returns a `CronbachAlpha` object that holds: |
| 29 | +
|
| 30 | +* `alpha`: the Cronbach's alpha score for all items, i.e. columns, in `covmatrix`; and |
| 31 | +* `dropped`: a vector giving Cronbach's alpha scores if a specific item, |
| 32 | + i.e. column, is dropped from `covmatrix`. |
| 33 | +
|
| 34 | +# Example |
| 35 | +```jldoctest |
| 36 | +julia> using StatsBase |
| 37 | +
|
| 38 | +julia> cov_X = [10 6 6 6; |
| 39 | + 6 11 6 6; |
| 40 | + 6 6 12 6; |
| 41 | + 6 6 6 13]; |
| 42 | +
|
| 43 | +julia> cronbachalpha(cov_X) |
| 44 | +Cronbach's alpha for all items: 0.8136 |
| 45 | +
|
| 46 | +Cronbach's alpha if an item is dropped: |
| 47 | +item 1: 0.7500 |
| 48 | +item 2: 0.7606 |
| 49 | +item 3: 0.7714 |
| 50 | +item 4: 0.7826 |
| 51 | +``` |
| 52 | +""" |
| 53 | +function cronbachalpha(covmatrix::AbstractMatrix{<:Real}) |
| 54 | + isposdef(covmatrix) || throw(ArgumentError("Covariance matrix must be positive definite.")) |
| 55 | + k = size(covmatrix, 2) |
| 56 | + k > 1 || throw(ArgumentError("Covariance matrix must have more than one column.")) |
| 57 | + v = vec(sum(covmatrix, dims=1)) |
| 58 | + σ = sum(v) |
| 59 | + for i in axes(v, 1) |
| 60 | + v[i] -= covmatrix[i, i] |
| 61 | + end |
| 62 | + σ_diag = sum(i -> covmatrix[i, i], 1:k) |
| 63 | + |
| 64 | + alpha = k * (1 - σ_diag / σ) / (k - 1) |
| 65 | + if k > 2 |
| 66 | + dropped = typeof(alpha)[(k - 1) * (1 - (σ_diag - covmatrix[i, i]) / (σ - 2*v[i] - covmatrix[i, i])) / (k - 2) |
| 67 | + for i in 1:k] |
| 68 | + else |
| 69 | + # if k = 2 do not produce dropped; this has to be also |
| 70 | + # correctly handled in show |
| 71 | + dropped = Vector{typeof(alpha)}() |
| 72 | + end |
| 73 | + return CronbachAlpha(alpha, dropped) |
| 74 | +end |
0 commit comments