Filtering Variables

From Q
Jump to navigation Jump to search

This QScript takes a linked copy of a question, but applies a filter to each variable according to the expressions shown in filter_expressions. Where filter_expressions contains only a single entry, this expression will be used to filter all the variables in the question. Where the expression contains multiple entries, they are cycled through one after each other (e..g, if var filter_expressions = ["q1 == 1","q1 == 2"], then the first, third, fifth etc. variables will all be filtered using q1 == 1.

You can download this code from FilteringVariables.QScript.

To use this QScript, you only need to modify the two lines at the top beginning with var, so that they indicate the question to be copied and the expressions to be applied.

// FILTERING VARIABLES
// Filters the variables in a question according to the specified filters in "filter_expression":

var question_to_filter = "Q2";//"Question Name as it appears in Q goes here";
var filter_expressions = ["q1 == 1","q1 == 2"];

// Utility functions documented on the wiki
function IsArray(x) {return x instanceof Array}
function Rep(x, k) {
    var n = x.length;
    if (!IsArray(x))
        return Rep([x],k);
    if (!IsArray(k)) {
        var result = new Array(n * k);
        for (var j = 0; j < k; j++)
            for (var i = 0; i < n; i++)
                result[i + j * n] = x[i];
        return result;
    }
    if (k.length != x.length)
        alert("If x and k are both arrays in 'Rep', then they need to have the same length.");
    var result = new Array();
    for (var j = 0; j < n; j++)
        for (var i = 0; i < k[j]; i++)
            result.push(x[j]);
    return result;
}
function copyValueAttributesForVariable(from_variable, to_variable){
    var n = from_variable.uniqueValues
    var values = from_variable.uniqueValues;
    var qt = to_variable.question.questionType;
    var qt_old = from_variable.question.questionType;
    if (qt != qt_old)
        alert("Question types are different.");
    for (var i=0; i<values.length; i++){
        var v = values[i];
        if (qt != "Text" && qt != "Text - Multi"){
            to_variable.valueAttributes.setLabel(v,from_variable.valueAttributes.getLabel(v));
            to_variable.valueAttributes.setIsMissingData(v,from_variable.valueAttributes.getIsMissingData(v));
            if (qt == "Pick Any" || qt == "Pick Any - Compact" || qt == "Pick Any - Grid")
                to_variable.valueAttributes.setCountThisValue(v,from_variable.valueAttributes.getCountThisValue(v));
            else
                to_variable.valueAttributes.setValue(v,from_variable.valueAttributes.getValue(v));
        }
    }
}
function copyValueAttributesForQuestion(from_question, to_question){
    var x = from_question.variables;
    var y = to_question.variables;
    if (y.length != x.length)
        alert('Questions contain different numbers of variables.');
    for (var j=0;j<x.length;j++)
        copyValueAttributesForVariable(x[j], y[j])
}

// creating the new variables
var group = project.report.appendGroup();// creating a group in the report to store the results
group.name = "Question with filtered variables";
for (var data_i in project.dataFiles){ //looping through all the data files
    var data_file = project.dataFiles[data_i];
    var question = data_file.getQuestionByName(question_to_filter); // getting the question
    var variables = question.variables;
    var n_variables =  variables.length;
    var n_times_to_copy_filter_expression = Math.floor(n_variables / filter_expressions.length);
    var filter_expressions = Rep(filter_expressions, n_times_to_copy_filter_expression);
    if (filter_expressions.length != n_variables)
        alert("filter_expressions does not contain the correct number of entries");
    var new_question_variables = [];
    for (var v = 0; v < n_variables; v++) {// creating the new variables
        var variable =  variables[v];
        var name = variable.name;
        var expression = "if(" + filter_expressions[v] + ") " +  name;
        var new_var = data_file.newJavaScriptVariable(expression, false, name + "_filtered",variable.label, null);
        new_question_variables.push(new_var);
    }
    var new_question = data_file.setQuestion(question.name + " Filtered", question.questionType, new_question_variables);
    copyValueAttributesForQuestion(question, new_question);  // copying any recoding or missing value settings
    data_file.moveAfter(new_question.variables, variables[n_variables - 1]); //putting the new question under the old question
    var t = group.appendTable();// add tables showing the new data
    t.primary = new_question;
}
log("All done");

See also