I have a series of variables populated by satisfaction scores from a survey. These scores are between 1 and 10, but can also be 99 signifying "I don't know".
Without a series of If statements, is is possible to calculate the mean of all the questions while excluding the 99s?
Apologies for the slightly odd way question data is retrieved in my example below. Each of the 3 questions has 3 measures which are given a satisfaction rating. The Confirmit survey platform I'm using uses f('x_y').get()
to fetch answers where x
= question ID and y
= measure so f('q3_1').get()
returns the score given to the 1st measure in question 3.
var qList = ['q3', 'q4', 'q6']; // 3 questions, each containing 3 satisfaction scores
var output
var i
for (i = 0; i < qList.length; i++){ // For each question in qList...
// Collect each satisfaction rating & convert to flaoting-point number:
var sat1 = parseFloat( f(qList[i].concat('_1')).get() );
var sat2 = parseFloat( f(qList[i].concat('_2')).get() );
var sat3 = parseFloat( f(qList[i].concat('_3')).get() );
// Calculate average satisfaction
var satAvg = (sat1 + sat2 + sat3) / 3;
if (satAvg == NaN){
output = "<em>Did not answer</em>";
} else {
output = satAvg.toString().concat('/10');
}
// Write to open-text questions:
f('av'.concat(i +1)).set(output)
}
The contents of the open-text av1, av2 & av3 questions populated by the above are concatenated into an email alert, keeping this alert short is why an average is required. Obviously having any "I don't know" responses is going to affect this mean.
EDIT: Based on @Cimbali's answer below, I'm now putting the values into an array. This means unwanted answers (11 & blanks) can be excluded by a single if statement in a loop:
var qList = ['q3', 'q4', 'q6'];
// Get satisfaction scores:
var i;
for (i = 0; i < qList.length; i++){
var answers = [
parseFloat( f(qList[i].concat('_1')).get() ),
parseFloat( f(qList[i].concat('_2')).get() ),
parseFloat( f(qList[i].concat('_3')).get() )
];
// Remove "I don't know" (11) and blank answers:
var y;
for (y = 0; y < answers.length; y++){
if ( answers[y] > 10 || isNaN(answers[y]) ){
answers.splice(y, 1);
}
}
// Calculate sum of remaining answers:
var sum = 0;
var x;
for (x = 0; x < answers.length; x++){
sum += answers[x];
}
// Calculate mean:
var average = sum / answers.length;
if ( isNaN(average) ){
// If mean couldn't be calculated, just enter 'N/A':
var output = "N/A";
} else {
// Round to 2 decimal places & add the '/10':
var output = average.toFixed(2).concat("/10");
}
// Write to open text questions:
f('av'.concat(i +1)).set(output);
}
However, I'm still interested to know of a quicker way.
Try putting them in an array and filtering the array.
Something like:
function validAnswer(n) { return !isNaN(n) && n <= 10; }
answers = [
parseFloat( f(qList[i].concat('_1')).get() ),
parseFloat( f(qList[i].concat('_2')).get() ),
parseFloat( f(qList[i].concat('_3')).get() )
].filter(validAnswer);
answers
now contains only the valid answers. Sum the array's contents and divide by its length to get the average. Remember you might have no valid answers at all.
This will make even more sense with a bigger array, in which case you'll probably want to fill the array with a loop rather than hardcoded like this.
function validAnswer(n) { return !isNaN(n) && n <= 10; }
// use functions to populate the array, hardcoded for the example
answers = [1, 2, 11, "not a valid number", 10].filter(validAnswer);
average = answers.length > 0 ? answers.reduce((val, sum) => val + sum) / answers.length: "N/A";
console.log("valid answers are [" + answers + "], average = " + average);
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments