QScript Scale Functions

From Q
Jump to navigation Jump to search

The functions below are used by the scaling QScripts under Create New Variables - Scale Within Case and Create New Variables - Scale Within Variable.

To make these functions available when writing a QScript or Rule see JavaScript Reference.

scaleOneQuestion(question, type, within_case)

This function takes one QScript Question and performs a scale transformation to it. See the next function for a description of the type and within_case arguments.

scaleQuestions(type, within_case)

This function uses variable sets selected by the user in Data Setsprompts the user to select questions and performs a scale transformation to each selection based on the type argument. Possible values for type are "rank", "standardize", "center", and "unit". If within_case is true, then the scaling is performed within case/respondent; otherwise, it is performed within variable. This is a wrapper for scaleOneQuestion.

Source Code

includeWeb("QScript Utility Functions");
includeWeb("QScript Selection Functions");
includeWeb("QScript Functions to Generate Outputs");
includeWeb("QScript R Output Functions");
 
function scaleOneQuestion(question, type, within_case) {
    var is_displayr = (!!Q.isOnTheWeb && Q.isOnTheWeb());
    var structure_name = is_displayr ? "variable set" : "question";
    
    var question_name = question.name;
    var data_file = question.dataFile;
    var new_question_name = (type == "unit" ? "unit scale" : type) + " within " +
                            (within_case ? "case" : "variable") + " for " + question_name;

    var new_question_name = preventDuplicateQuestionName(data_file, new_question_name);
    var temp_var_name = randomVariableName(16); // temporary name, random to (almost) guarantee uniqueness
    var variables = question.variables; 
    var var_labs = variables.map(x => x.label);

    if(variables.length === 1 && within_case){
        var msg = 'Scaling within case for ' + structure_name + ' ' + question_name + ' is not meaningful ' + 
		  'since it consists of only a single variable.';
        log(msg);
        return false;
    }
    
    var expression = 'flipTransformations::ScaleVariableSet(' + stringToRName(question.name) + ', type = "' + type + 
                     '", within.case = ' + within_case.toString().toUpperCase() + ')';

    try {
	var new_r_question = data_file.newRQuestion(expression, new_question_name, temp_var_name, variables[variables.length - 1]);
 	var new_r_variables = new_r_question.variables;

	if(/Number/.test(question.questionType)) {
	    new_r_question.questionType = question.questionType;
	} else if(/Multi$/.test(question.questionType)){
	    new_r_question.questionType = "Number - Multi";
	}
    insertAtHoverButtonIfShown(new_r_question);
		
    } catch (e) {
        function errorFun(e){
            log("The transform could not be computed for " + structure_name + " " + question_name + " : " + e.message);
	    return false;
        }
        if (/R code is ambiguous/.test(e.message)){
            expression = 'flipTransformations::ScaleVariableSet(' + stringToRName(data_file.name) + '$Questions$' + 
                          stringToRName(question.name) + ', type = "' + type + 
                          '", within.case = ' + within_case.toString().toUpperCase() + ')';
            try {
                var new_r_question = data_file.newRQuestion(expression, new_question_name, temp_var_name, 
                                                            variables[variables.length - 1]);
                if(/Number/.test(question.questionType)) {
                    new_r_question.questionType = question.questionType;
                } else if(/Multi$/.test(question.questionType)){
                    new_r_question.questionType = "Number - Multi";
                }                
                insertAtHoverButtonIfShown(new_r_question);

            } catch(e){
                return errorFun(e);
            }
        }else{           
            return errorFun(e);
        }
    }

    // Replace temporary variable names
    var base_var_name = question_name.replace(/[^a-zA-Z0-9_@\#\$\\]/g, '_').toLowerCase() + "_" + type + "_scaled";
    nameSequentialVariables(new_r_question.variables, base_var_name);
    var top_group_name = type.slice(0,1).toUpperCase() + type.slice(1) + (type == "unit" ? " scale " : "") + 
                   " within " + (within_case ? "case" : "variable") + " Transformation";
    reportNewRQuestion(new_r_question, top_group_name);
    return true;
}

function scaleQuestions(type, within_case) {
           
    if (within_case)
        var allowed_types = ["Nominal - Multi", "Ordinal - Multi", "Numeric - Multi", "Numeric - Grid"];
    else
        var allowed_types = ["Nominal - Multi", "Ordinal - Multi", "Numeric - Multi", "Numeric - Grid", "Nominal", "Ordinal", "Numeric"];
    var selected_questions = selectInputQuestions(allowed_types);
    if (!selected_questions)
        return false;

    var results = [];
    for (let i = 0; i < selected_questions.length; i++)
        results.push(scaleOneQuestion(selected_questions[i], type, within_case));
    
    var success = results.some(function(x){return(x)});
    return success;
}

See also