# Modifying Tables or Plots - Showing Average Rank

This rule adds an additional Statistic to a SUMMARY of a Number - Multi question, showing the Average Rank.

## Technical details

1. This Rule requires Q 4.11 or later.
2. By default, the highest value is given the highest rank. For example, if there are 6 items, the value with the highest value is given a rank of 6, even if all the other values are missing. If Reverse ranking (highest score is given a rank of 1) is checked, the highest value is instead given a value of 1.
3. Where Treatment of ties is set to Average rank, tied values are assigned the average rank. For example, if there are 6 items, and three of them share the highest value, they will be given a rank of 5 (i.e., (4 + 5 + 6) / 3). Where set to Highest rank, the highest possible value is set. For example, if there are 6 items, and three share the highest value, they are all assigned a value of 6, unless Reverse ranking (highest score is given a rank of 1) is checked, in which case they are assigned a value of 1.
4. Where Treatment of ties is set to Average rank and Reverse ranking (highest score is given a rank of 1) is checked, this corresponds to the Excel function RANK.AVG.
5. Where Treatment of ties is set to Highest rank and Reverse ranking (highest score is given a rank of 1) is checked, this corresponds to the deprecated Excel function RANK.
6. NETs are given ranks of NaN.

## How to apply this rule

### For the first time in a project

• Select the table(s)/chart(s) that you wish to apply the rule to.
• Start typing the name of the Rule into the Search features and data box in the top right of the Q window.
• Click on the Rule when it appears in the QScripts and Rules section of the search results.

OR

• Select Automate > Browse Online Library.
• Choose this rule from the list.

### Additional applications of the rule

• Select a table or chart that has the rule and any table(s)/chart(s) that you wish to apply the rule to.
• Click on the Rules tab (bottom-left of the table/chart).
• Select the rule that you wish to apply.
• Click on the Apply drop-down and choose your desired option.
• Check New items to have it automatically applied to new items that you create. Use Edit > Project Options > Save as Template to create a new project template that automatically uses this rule.

## Removing the rule

• Select the table(s)/chart(s) that you wish to remove the rule from.
• Press the Rules tab (bottom-right corner).
• Press Apply next to the rule you wish to remove and choose the appropriate option.

## How to modify the rule

• Click on the Rules tab (bottom-left of the table/chart).
• Select the rule that you wish to modify.
• Click Edit Rule and make the desired changes. Alternatively, you can use the JavaScript below to make your own rule (see Customizing Rules).

## JavaScript

```// Checking if the rule is applicable
var blue = table.blueQuestion;
if (blue.questionType != "Number - Multi" || table.brownQuestion != "SUMMARY")
form.ruleNotApplicable("This rule requires a table that is a SUMMARY of a Number - Multi question.");

var statistic_to_replace = "Not Duplicate";

// Creating form.
if (fileFormatVersion() < 8.81) {
} else {
var reverse_checkbox = form.newCheckBox("Highest1", "Reverse ranking (highest score is given a rank of 1)");
reverse_checkbox.lineBreakAfter = true;
reverse_checkbox.setDefault(false);

var tie_treatment =  ["Average rank", "Highest rank"];
var ties_combo = form.newComboBox('ties', tie_treatment);
ties_combo.setDefault(tie_treatment[0]);
var tie_label = form.newLabel("Treatment of ties");
form.setInputControls([reverse_checkbox, tie_label, ties_combo]);

// Extracting values from form.
var reverse = reverse_checkbox.getValue();
var average_rank = ties_combo.getValue() == tie_treatment[0];

// Function for sorting and cleaning the data.
var not_duplicates_raw = table.get("Not Duplicate");
var n_variables = not_duplicates_raw.length;
var not_duplicate = new Array(n_variables);
var n_non_NET = 0;

for (var i = 0; i < n_variables; i++) {
not_duplicate[i] = not_duplicates_raw[i][0] == 1;
if (not_duplicate[i])
n_non_NET++;
}
sortValues = function(x) {
var result = [];
for(var i = 0; i < n_variables; i++) {
var v = x[i];
if (not_duplicate[i]  && !isNaN(v))
result.push(v);
}
return(result.sort(function(a, b){return b - a}));
}

// Computing average ranks.
var wgt = table.weight;
if (wgt != null)
wgt = wgt.rawValues;
var raw_table = calculateTable(table.blue, "RAW DATA", ['!UseQFilters'], null);
var raw_data = raw_table.get("Values");
var n = raw_data.length;
var ranks = new Array(n_variables);
var base = new Array(n_variables);
for (var c = 0; c < n_variables; c++) {
ranks[c] = 0;
base[c] = 0;
}
var sum = new Array(n_variables);
for (var i = 0; i < n; i++) {
var respondent_data = raw_data[i];
var values = sortValues(respondent_data);
var n_values = values.length;
var rank_lookup = new Array(n_values);
var position = 0;
while (position < n_values) {
var n_ties = 1;
while(values[position] == values[position + n_ties] && position + n_ties < n_values)
n_ties++;
var rank = average_rank ? position + (n_ties + 1) / 2 : position + 1;
for (var tie = 0; tie < n_ties; tie++) {
rank_lookup[position + tie] = rank;
}
position += n_ties;
}
//alert(respondent_data + " " + not_duplicate + " " + rank_lookup + " " + values);
if(!reverse)
for(var c = 0; c < n_values; c++)
rank_lookup[c] = n_non_NET + 1 - rank_lookup[c];
var respondent_ranks = new Array(n_variables);
for(var c = 0; c < n_variables; c++) {
var v = respondent_data[c];
if(not_duplicate[c] && !isNaN(v))
respondent_ranks[c] = rank_lookup[values.indexOf(v)];
}
// Computing the average acroess respondents. NB: can be optimized by including in previous loop.
if (wgt == null) {
for (var c = 0; c < n_variables; c++) {
var r = respondent_ranks[c];
if (r != null) {
base[c]++;
ranks[c] += r;
}
}
} else {
var w = wgt[i];
for (var c = 0; c < n_variables; c++) {
var r = respondent_ranks[c];
if (r != null) {
base[c] += w;
ranks[c] += r * w;
}
}
}
}

var table_data = table.get(statistic_to_replace);
for (var c = 0; c < n_variables; c++)
table_data[c][0] = ranks[c] / base[c];
table.set(statistic_to_replace, table_data);

// Get the existing statistics on the table (selected by the context menu).
var stats = table.statistics;
if (stats.indexOf(statistic_to_replace) == -1)
stats.push(statistic_to_replace);
table.statistics = stats;
form.setTranslation(statistic_to_replace, "Average Rank");
}```