Cronbach alpha for reliability test, i tinkering with rust

You know cronbach alpha is the really famous reliability test if you are doing test your research and make sure your questionnaire reliable. Why i discuss this? because, recently i had mini research group assignment from my lecturer. And yeah, absolutely we must be make sure test validity and reliability suitable. Thats why i’m thinking to create some function cronbach alpha in rust.
Cronbach’s alpha, often referred to as cronbach alpha or coefficient alpha, is a statistical measure used to assess the internal consistency or reliability of a scale or questionnaire. It is named after the American psychologist Lee Joseph Cronbach, who developed the concept (Cronbach, 1951).

Ok, first i would like to show you sample data, maybe sample data like table in this below and using most of familiar statement answer likert scale. Define answer range 1–4 to choose and after the questionnaire is completed, each item may be analyzed and it contains 10 question and 16 sample respondent. Likert scales are often called summative scales.
Ok lets move out and i would like to starting code, first of all i’m creating new project library with — lib it means making a library in rust. Why library? I don’t want only to build project and let it go, i want to share and maybe there is someone who will wants to use it.
cargo new crate_name --lib
And i would like to create main function and convert table data in above to multi dimensional(2d) array in rust such as code in below. Remember, the array is a fixed-size list of elements and a vector is kind of a re-sizable array but all elements must be in the same type.
fn main() {
// 10 * 15
let data = vec![
vec![1,3,3,3,2,2,2,2,1,1,1,3,4,3,4], // Q1 = question 1
vec![2,2,2,2,3,3,3,3,4,4,4,4,3,3,3], // Q2 = question 2
vec![1,3,3,3,3,3,3,3,3,4,4,3,4,2,2], // Q3 = question 3
vec![2,1,2,2,3,3,3,4,4,4,4,1,1,1,1], // Q4 = question 4
vec![3,3,3,4,4,4,4,3,3,3,3,3,3,3,3], // Q5 = question 5
vec![2,3,3,3,3,4,4,4,1,2,2,2,2,3,3], // Q6 = question 6
vec![1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], // Q7 = question 7
vec![2,3,2,2,2,2,2,2,2,2,2,2,1,1,1], // Q8 = question 8
vec![3,3,3,4,2,2,2,2,2,2,2,3,3,3,3], // Q9 = question 9
vec![2,2,2,3,1,1,2,2,4,4,3,2,2,2,4] // Q10 = question 10
];
}
Then, i create variance function you know i must be to find cronbach alpha value to be measure of variability. Before looking for variance value usually we have to find the mean value and yup absolutely i musty create mean function to find the average value of a group of numbers
fn mean(data: &[i32]) -> Option<f32> {
let sum = data.iter().sum::<i32>() as f32;
let count = data.len();
match count {
positive if positive > 0 => Some(sum / count as f32),
_ => None,
}
}
fn variance(data: &[i32]) -> Option<f32> {
match (mean(data), data.len()) {
(Some(data_mean), count) if count > 0 => {
let variance = data.iter().map(|value| {
let diff = data_mean - (*value as f32);
diff * diff
}).sum::<f32>() / ((count as f32) - 1.0);
Some(variance)
},
_ => None
}
}
Next, also to calculated each question with another side question and then find variance value. So, i think try to transposed data change column to row and vice versa. The function like in below
fn transposed(arr: &[Vec<i32>]) -> f32 {
let m = arr.len();
let n = arr[0].len();
let mut transposed_data: Vec<Vec<i32>> = vec![vec![0; m]; n];
let mut sum_all_tranposed: Vec<i32> = vec![];
for i in 0..m {
for j in 0..n {
transposed_data[j][i] = arr[i][j];
}
}
for t in transposed.iter(){
sum_all_tranposed.push(t.iter().sum::<i32>())
}
let std_dev = variance(&sum_all_tranposed);
if std_dev.is_some() {
std_dev.unwrap()
}else{
0.0
}
}
And previously i had create main function and finally update some of code of that like in below
fn main() {
// 10 * 15
let data = vec![
vec![1,3,3,3,2,2,2,2,1,1,1,3,4,3,4],
vec![2,2,2,2,3,3,3,3,4,4,4,4,3,3,3],
vec![1,3,3,3,3,3,3,3,3,4,4,3,4,2,2],
vec![2,1,2,2,3,3,3,4,4,4,4,1,1,1,1],
vec![3,3,3,4,4,4,4,3,3,3,3,3,3,3,3],
vec![2,3,3,3,3,4,4,4,1,2,2,2,2,3,3],
vec![1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
vec![2,3,2,2,2,2,2,2,2,2,2,2,1,1,1],
vec![3,3,3,4,2,2,2,2,2,2,2,3,3,3,3],
vec![2,2,2,3,1,1,2,2,4,4,3,2,2,2,4]
];
let items_variance: Vec<f32> = vec![];
let transposed = transposed(&items);
let k: f32 = items.len() as f32 / (items.len() as f32 - 1.0);
let mut result: f32;
for i in items.iter() {
let variance_data = variance(&i);
items_variance.push(variance_data.unwrap());
}
result = items_variance.iter().sum::<f32>(); // sum all varians
result = 1.0 - (&result / transposed); // 1-(∑ σ_b^2)/(σ_t^2 )
result = format!("{:.3}", k * &result).parse().unwrap(); // format fixed decimal
println!("cronbach alpha value: {}", &result);
}
Maybe i would like to additional little bit information function to check the value reliable or not. This is depend on the condition and i would like use to fulfill good reliability test, composite reliability value cronbach alpha should be more than 0,70 (Chin, 1998).
fn is_reliable(reliable_value: f32) -> bool {
if reliable_value > 0.7 {
println!("is reliable");
} else {
println!("is not reliable");
}
return reliable_value > 0.7;
}
Reference:
Cronbach, L. J. (1951). Coefficient alpha and the internal structure of tests. Psychometrika, 16, 297–334
Chin, W. W. (1998). The Partial Least Squares Aproach to Structural Equation Modeling. Modern Methods for Business Research, 295, 336.