What is piping and looping?
Sometimes in surveys, the same question is asked multiple times, but with the insertion of a different item every time the question is asked. The insertion of the item is what is known as piping. The item could be a brand, a product, a concept, or perhaps a statement (or other). The multiple presentation of the same question is called looping. The order of presentation of the items within a loop can be rotated or randomised. This page shows you how you can work with this data for analysis.
- An illustration of the problem
- The item key
- We present 4 possible solutions for de-looping and/or de-piping the data structured as per the example outlined in the 2 sections above:
An illustration of the problem
A worked example is captured in this Depiping delooping example.QPack. In a loop, the same question, “How often do you drink <BRAND>?” could be asked three times. Each iteration of the loop pertains to a different brand (the item that’s piped in). Suppose there were 6 possible brands (Coke, Diet Coke, Coke Zero, Pepsi, Pepsi Max, Diet Pepsi), but only 3 questions asking about how often each gets drunk.
One respondent gets asked:
- How often do you drink Coke?
- How often do you drink Pepsi?
- How often do you drink Fanta?
But another respondent is asked:
- How often do you drink Pepsi?
- How often do you drink Diet Coke?
- How often do you drink Pepsi Max?
And so forth, with the brands rotating/randomizing across respondents.
The data may be stored in variables that indicate the order of presentation as opposed to variables that store information about the specific items. In the cola example above, the data file could have 3 variables:
- var1 = How often do you drink <BRAND_1>?
- var2 = How often do you drink <BRAND_2>?
- var3 = How often do you drink <BRAND_3>?
For one case, BRAND_1 is Coke at var1, whereas for another BRAND_3 is Coke, and in another case is not presented with Coke at all (because only 3 brands were asked about, and there are 6 potential brands).
Storing the data in that way makes sense from a data collection perspective, but it is not useful from an analysis perspective. A researcher typically needs to know the frequency of drinking each brand, not the frequency of drinking whatever brand was presented first.
Building on the above cola example, if you had six possible brands included in the loop, then, for analysis purposes, you would need 6 variables:
- varA = How often do you drink Coke?
- varB = How often do you drink Diet Coke?
- varC = How often do you drink Coke Zero?
- varE = How often do you drink Pepsi?
- varF = How often do you drink Pepsi Max?
- varG = How often do you drink Diet Pepsi?
The variables A through G above we term delooped/depiped variables.
The item key
The rotation of the items used in the piping is typically stored in separate variable(s), which we term the item key. The item key is what the survey platform draws on to generate each question (which, as discussed, changes for each respondent).
In our cola example, a question could have been asked earlier in the survey: “Which of the following colas have you consumed in the past month?”, and then up to three of the colas are stored in the item key.
So in the above cola example, there would likely be three variables that form an item key:
- hBrand1 – First brand selected for the loop
- hBrand2 – Second brand selected for the loop
- hBrand3 – Third brand selected for the loop
Normally, the item key is hidden from the respondent. It is only used for the purposes of the (online) survey scripting. Because it’s often hidden, it can often have “h”, “hidden”, “d”, or “dummy” in the variable label(s).
The challenge for the researcher is to use the item key to generate new variables that pertain to each possible item. That is, getting the variables de-looped and/or de-piped. In the cola example above, that is creating varA through varG.
We present 4 possible solutions for de-looping and/or de-piping the data structured as per the above example:
- Solution 1: Get your data provider to set up the data for you
- Solution 2: Use a QScript
- Solution 3: Create custom JavaScript variables
- Solution 4: Using built-in automations
Solution 1: Get your data collection platform to set up the data for you
The best solution is to get your data collection platform to do this for you. That is, to set up your survey and variables in such a way that they are de-looped and de-piped. The datafile specifications for Displayr/Q should be adhered to (so that automatic setup of variable sets/questions is optimized).
Solution 2: Use a QScript
The next best solution is to use a custom QScript (only available to Displayr Enterprise and Q customers). The QScript below will prompt you for which variable sets contain the item key and the data to deloop. The item key must be in a Nominal – Multi/Pick One-Multi structure so the categories are consistent across each variable in the item key. The final output of the script will be the delooped data combined into one set for each item in the key (usually a brand). The QScript essentially creates a new JavaScript variable (as per solution 3) many times over.
You can also use this script as a starting point, if need be, which you can adapt to your purposes.
includeWeb("QScript Selection Functions");
includeWeb("QScript Utility Functions");
includeWeb("QScript Functions to Generate Outputs");
includeWeb("QScript Data Reduction Functions");
includeWeb("QScript Value Attributes Functions");
function modified_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));
};
};
};
if (!main())
log("QScript cancelled.");
else
conditionallyEmptyLog("QScript finished.");
function main() {
// Get the user to select one data file when there is more than one.
var data_file = requestOneDataFileFromProject();
// Get the user to select the rotation question
var rotationPOM = getAllQuestionsByTypes([data_file], ["Pick One - Multi"]);
var rotation = selectOneQuestion("Select the Pick One - Multi question that stores the rotations:", rotationPOM, true);
//Calculates the number of iterations involved
var rotation_variables = rotation.variables;
var n_iterations = rotation_variables.length
//Gets non-Missing values from the rotation question
indicator = valueAttributesMissingValueIndicatorArray(rotation)
var d = rotation.uniqueValues;
var brand_values = [];
for (i = 0; i < d.length; i++) {
if (!isNaN(d[i]) && indicator[i] == 0) {
brand_values.push(d[i]);
}
}
var brand_labels = [];
brand_labels = nonMissingValueLabels(rotation);
var loops = [];
// Get the user to select the first question
for (i = 1; i < (n_iterations + 1); i++) {
var x = getAllQuestionsByTypes([data_file], ["Pick One", "Pick One - Multi","Pick Any","Number","Number - Multi","Pick Any - Grid"]);
var x = selectOneQuestion("Select iteration " + i + " of the loop", x, true);
loops.push(x)
}
var loops_variables = loops.map (function (v) { return v.variables; } );
var n_variables = loops_variables[0].length
// Note: b rotates the brand
for (b = 0; b < brand_values.length; b++) {
var new_q_vars = [];
for (p = 0; p < n_variables; p++) {
var expression = "var _result = NaN;\r\n"
for (i = 0; i <n_iterations; i++) {
if (i > 0)
expression += "else "; expression += "if (" + rotation_variables[i].name + " == " + brand_values[b] + ") _result = " + loops_variables[i][p].name +";\r\n"
}
expression += "_result;"
var new_name = loops_variables[0][p].name + "_deloop";
new_name = preventDuplicateVariableName(data_file, new_name);
var new_label = preventDuplicateQuestionName(data_file, loops_variables[0][p].label);
var new_name = preventDuplicateVariableName(data_file, new_name);
var new_var = data_file.newJavaScriptVariable(expression, false, new_name, new_label, null);
new_var.question.name = loops_variables[0][p].question.name + p + " - " + brand_labels[b];
var type = loops_variables[0][p].variableType;
new_var.variableType = type;
data_file.moveAfter([new_var],data_file.variables[data_file.variables.length-1]);
modified_copyValueAttributesForVariable(loops_variables[0][p],new_var);
new_q_vars.push(new_var);
};
var new_q_name = loops[0].name + " - " + brand_labels[b];
var question_type = loops[0].questionType;
data_file.setQuestion(new_q_name, question_type, new_q_vars);
};
return true
}Solution 3: Create custom JavaScript variables
If you cannot get the data set up by your data supplier and you only have a few items/looped variable sets, then you can create new variables manually. You would create a new variable for each unique variable (i.e., emotional attribute, statement, etc) that was looped for each item (i.e., brand). This can be accomplished using a custom JavaScript variable in Displayr/Q.
An example of the expression one may write:
//set x to the code for the specific item from your set of items that were shown in the looping
x = 1
//check each variable that lists the item shown for each loop (hBrand1, 2, 3 below)
//if the specific item was shown in a loop for a respondent pull in the response from the
//appropriate looped variable
if (hBrand1 == x) var1;
else if (hBrand2 == x) var2;
else if (hBrand3 == x) var3;
else NaN;The above code, from the illustrated example, checks the value of each variable in the hBrand set. If any of the hBrand variables equals 1 (i.e., the first brand, e.g., “Coke), then it returns the corresponding piped variable. So the resultant variable would be for “Coke” only. The easiest way to create variables for that data for the other items is to duplicate the variable and change the x to the appropriate new number.
An example of JavaScript variables untangling a pipe/loop can be seen in this example Depiping delooping example.QPack. The last 3 variables have been constructed with custom numeric JavaScript variables. In Q, if you edit these variables (right-click > Edit Variable), you can see how the expression uses the variables the item key (the hBRAND Pick One - Multi question,) de-pipe question 5.
Solution 4: Using built-in automations
Another way to achieve delooping is to use a combination of point-and-click functions to filter each piped question using a key and then merge back together. This is a more automated way than solution 3 for Displayr customers without the ability to run custom QScripts. Although this works, it can be very convoluted for large variable sets and grids, and when there are lots of variables that need de-piping.
It is a multi-step process:
Step 1: Make sure the item key and target question is set up appropriately If the item key is a Nominal – Multi (Pick One-Multi), you will need to split it into separate Nominal variables (right-click > Split or Split Variables from Question in Q). This is so they can be used as filter variables in the next step. You may need to split variables from your target question in the same way so that the appropriate filter is applied to the appropriate question (eg, the first item key to only the first iteration in the target question loop).
Step 2: Create new variables that expand the item x iteration Select the first piped variable set and hover and click + > Filter > Filter One Variable Set by Another. Select the piped question (answer from the respondent) as the target to be filtered, and the item key (brands that were shown each time in this example) as the filter. This will create new variables for each item for the specific question. Repeat this as necessary for each loop/piped question.
Step 3: Merge each of the item variables back into one (to remove the order effect) Select all the new variables that pertain to a particular item (i.e. brand that was shown), and then click Tools in the top left > Combine > As Variable Set > Merge Variables (see merge questions for Q). Do this as many times as there are items. You may wish to hide the input questions and set the resultant variables back into a question via Combine (or Set Question in Q).