This article describes how to go from a table with NETs...
...to a table that groups or indents categories within each NET:
Requirements
A Nominal, Binary Multi, or Binary Multi (Compact) table with NETs that don't overlap between categories.
Method
1. Select your table.
2. To sort your table from highest to lowest, for example, you will need to apply a sorting rule via Data > Rules > Plus (+) > Sort/Reorder Rows or Columns > Sort Rows (Automatically Updates When Data Changes). See How to Automatically Sort Table Rows for further details.
3. Next, to add a rule that groups the sub-categories within each NET category, go to Data > Rules on the object inspector.
4. Click the Plus (+) button > New custom rule (write your own JavaScript) > Edit JavaScript.
5. Paste the below into the dialog:
includeWeb("JavaScript Array Functions");
form.setHeading("Group rows according to NETs");
form.setSummary("Group rows according to NETs");
var blue_question = table.blueQuestion;
var data_reduction = blue_question.dataReduction;
var use_codes;
if (["Nominal", "Ordinal", "Binary - Multi (Compact)"].indexOf(blue_question.variableSetStructure) > -1)
use_codes = true;
else if (["Binary - Multi"].indexOf(blue_question.variableSetStructure) > -1)
use_codes = false;
else
form.ruleNotApplicable("the question selected in the Rows drop-down is not Binary - Multi, Nominal, or Binary Multi - Compact");
if (arrayHasDuplicateElements(table.rowLabels))
form.ruleNotApplicable("there are duplicate row labels in the table")
var indent_label = " - ";
// Row weights are used to keep children in the correct order.
var row_weights = {};
// Find underlying row sources
var row_values = table.rowLabels
.filter(function (label) {
return label !== 'NET';
})
.map(function (label, i) {
row_weights[label] = i;
return {
label: label,
sources: use_codes
? data_reduction.getUnderlyingValues(label)
: data_reduction.getUnderlyingVariables(label).map(function (v) {
return v.name;
})
}
});
// Create a map of the rows that are sourced from a single variable
var individual_values_map = {};
row_values
.filter(function (value) {
return value.sources.length === 1;
})
.forEach(function (value) {
individual_values_map[value.sources[0]] = {label: value.label, source: value.sources[0]}
});
// Populate the rows with multiple sources with their visible individual row data
var net_values = row_values
.filter(function (value) {
return value.sources.length > 1;
})
.map(function (value) {
var new_value = {
label: value.label,
sources: value.sources,
children: value.sources
.map(function (source) {
return individual_values_map[source];
})
.filter(function (source) {
return typeof source !== 'undefined'
})
};
new_value.children.sort(function (a, b) {
return row_weights[b.label] - row_weights[a.label];
});
return new_value;
});
// Create an array to store the labels that have been updated.
var changed_row_labels_map = {};
for (var i = 0; i < net_values.length; i++) {
var value = net_values[i];
value.children.forEach(function (child) {
table.moveRowAfter(table.rowIndex(child.label), table.rowIndex(value.label));
changed_row_labels_map[child.label] = indent_label + child.label;
});
}
table.rowLabels = table.rowLabels.map(function (label) {
return typeof changed_row_labels_map[label] !== 'undefined' ? changed_row_labels_map[label] : label;
});
- This code first checks that the underlying variable in the table is of the correct data type.
- It then loops through the underlying categories for each NET and places them directly below the relevant NET with an indent character prefixed to the label.
6. OPTIONAL: Change indent_label to include a different indent character for the categories within each NET.
7. Press the blue Play button > OK > OK.
Next
How to Modify Table Rows and Columns Using a Rule
How to Automatically Sort Table Rows