QScript Functions for Driver Analysis
Jump to navigation
Jump to search
This page contains functions created specifically for use with the driver analysis QScripts:
- Regression - Legacy Driver Analysis - Table of Linear Regression Coefficients
- Regression - Legacy Driver Analysis - Table of Contribution Scores
- Regression - Legacy Driver Analysis - Table of Beta Scores
- Regression - Legacy Driver Analysis - Table of Kruskal Importance Scores
- Regression - Legacy Driver Analysis - Table of Shapley Importance Scores
- Regression - Legacy Driver Analysis - Table of Relative Weights (Relative Importance Analysis)
- Regression - Legacy Driver Analysis - Table of Elasticity Scores
Source Code
includeWeb('QScript Selection Functions');
// Main driver analysis function that takes the analysis name (e.g. Kruskal Importance)
// and prompts the user for input variables, then creates a table with the driver analysis
// rule attached.
// The list of possible analysis names are:
// -'Linear Regression Coefficients'
// -'Contribution'
// -'Beta'
// -'Kruskal Importance'
// -'Shapley Importance'
// -'Relative Importance'
function driverAnalysis(analysis_name) {
var positive_inputs_only = analysis_name == 'Elasticity';
var is_kruskal = analysis_name == 'Kruskal Importance';
var is_kruskal_shapley_ria = analysis_name == 'Kruskal Importance' || analysis_name == 'Shapley Importance' || analysis_name == 'Relative Importance';
var is_shapley = analysis_name == 'Shapley Importance';
var version = fileFormatVersion();
if (version < 8.21) {
log('This script is not able to run on this version of Q. Please upgrade to the latest version of Q.');
return false;
}
var data_files = project.dataFiles;
var dependent_question, independent_question, show_confidence_intervals;
var candidate_questions = [];
data_files.forEach(function (data_file) {
candidate_questions = candidate_questions.concat(data_file.questions.filter(isQuestionNumCat).filter(isQuestionNotHidden).filter(isQuestionValid).filter(function (q) { return !q.isBanner; }));
});
if (candidate_questions.length == 0) {
alert('There are no suitable questions in this project.');
return false;
}
if (positive_inputs_only) {
candidate_questions = candidate_questions.filter(hasOnlyPositiveVariables);
if (candidate_questions.length == 0) {
alert('There are no questions with only positive values.');
return false;
}
}
var candidate_variables = getVariablesFromQuestions(candidate_questions).filter(isNotDriverAnalysisVariable);
// Select dependent question
var v_dependent = data_files.length == 1 ?
selectOneVariableByQuestionNameAndLabel('Select the dependent Variable:', candidate_variables, false) :
selectOneVariableByQuestionNameAndLabelAndDataFile('Select the dependent Variable:', candidate_variables, false);
var name;
if (v_dependent.question.variables.length > 1)
name = v_dependent.question.name + ': ' + v_dependent.label + ' (linked)';
else
name = v_dependent.question.name + ' (linked)';
dependent_question = createQuestionWithLinkedVariables(name, [v_dependent], v_dependent.question.dataFile , 'Number', true);
addDriverAnalysisStamp(dependent_question);
// Select independent question
while (independent_question == null) {
var v_independent = data_files.length == 1 ?
selectManyVariablesByQuestionNameAndLabel('Select the independent Variables:', candidate_variables, false).variables :
selectManyVariablesByQuestionNameAndLabelAndDataFile('Select the independent Variables:', candidate_variables, false).variables;
if (checkTwoOrMoreVariables(v_independent) && checkVariablesAreFromSameDataFile(v_independent)) {
independent_question = createIndependentQuestion(v_independent, dependent_question.variables[0]);
addDriverAnalysisStamp(independent_question);
}
}
var num_independent_vars = independent_question.variables.length;
if (is_kruskal || is_shapley) {
if (num_independent_vars > 27) {
alert('Warning: ' + num_independent_vars + ' indepedent Variables were selected in this analysis. However, it is not possible to compute a ' + analysis_name + ' Analysis ' +
'with more than 27 independent Variables due to limitations in the algorithm. Johnson\'s Relative Weights algorithm (Relative Importance Analysis) has been used instead; it gives very similar results');
analysis_name = 'Relative Importance';
} else {
if (num_independent_vars > 15) {
var prompt_message = 'Warning: this model contains ' + num_independent_vars + ' independent Variables. Depending on the number of observations in the data, ' + analysis_name + ' Analysis ' +
'results can be slow to compute when there are more than 15 independent Variables in the model. ' +
'Johnson\'s Relative Weights algorithm (Relative Importance Analysis) is recommended instead since it is much faster to compute and it gives very similar results. ' +
'Would you like to use Relative Importance Analysis instead? ' +
'Alternatively click Cancel if you wish to cancel this QScript.';
if (askYesNo(prompt_message, 'https://wiki.q-researchsoftware.com/wiki/Driver_(Importance)_Analysis'))
analysis_name = 'Relative Importance';
}
}
}
show_confidence_intervals = askYesNo('Would you like to display confidence intervals for importance estimates?');
var table = project.report.appendTable();
table.primary = independent_question;
if (analysis_name == 'Elasticity')
table.translations.set('Average', analysis_name);
else
table.translations.set('Average', analysis_name + ' (%)');
table.translations.set('Missing n', 'Raw ' + analysis_name);
table.translations.set('SUM', 'R-Squared (%)');
table.translations.set('Base n', 'Lower Confidence Bound 0.025');
table.translations.set('Effective Base n', 'Upper Confidence Bound 0.975');
table.translations.set('Expected Average', 'Expected Coefficient');
if (analysis_name == 'Elasticity')
table.cellStatistics = show_confidence_intervals ? ['Average', 'Base n', 'Effective Base n'] : ['Average'];
else
table.cellStatistics = show_confidence_intervals ? ['Average', 'Base n', 'Missing n', 'Effective Base n'] : ['Average'];
var format;
if (analysis_name == 'Elasticity')
table.setDecimalPlaceFor('Average', 3);
table.setDecimalPlaceFor('Expected Average', 3);
table.setDecimalPlaceFor('Base n', 3);
table.setDecimalPlaceFor('Missing n', 3);
table.setDecimalPlaceFor('Effective Base n', 3);
table.setDecimalPlaceFor('Standard Error', 3);
table.setDecimalPlaceFor('t-Statistic', 1);
if (dependent_question.dataFile.id) { // Remove when Q 4.10 is stable
format = project.rules.newCustomRule('driverAnalysisRule();\n' + driverAnalysisRule.toString(),
{ dependentQuestionName: dependent_question.name,
dependentDataFileName: dependent_question.dataFile.name,
dependentDataFileId: dependent_question.dataFile.id,
analysisName: analysis_name,
independentQuestionName: independent_question.name });
} else {
format = project.rules.newCustomRule('driverAnalysisRule();\n' + driverAnalysisRule.toString(),
{ dependentQuestionName: dependent_question.name,
dependentDataFileName: dependent_question.dataFile.name,
dependentDataFileId: '',
analysisName: analysis_name,
independentQuestionName: independent_question.name });
}
table.rules.add(format);
if (project.report.setSelectedRaw) // Remove when Q 4.10 is stable
project.report.setSelectedRaw([table]);
table.name = analysis_name + ' for ' + dependent_question.variables[0].label;
log('A driver analysis table has been added to the project.');
return true;
}
function hasOnlyPositiveVariables(question) {
if (question.questionType == 'Pick Any' || question.questionType == 'Pick Any - Grid')
return false;
var variables = question.variables;
for (var i = 0; i < variables.length; i++) {
var raw_values = variables[i].rawValues;
var value_attributes = variables[i].valueAttributes;
for (var j = 0; j < raw_values.length; j++)
if (value_attributes.getValue(raw_values[j]) <= 0)
return false;
}
return true;
}
function checkTwoOrMoreVariables(variables) {
if (variables.length >= 2)
return true;
alert('There needs to be two or more independent Variables.\n\nClick OK to reselect Variables or Cancel to stop the script.');
return false;
}
function isDriverAnalysisVariable(variable) {
return variable.name.match(/_DriverAnalysis\d*$/);
}
function isNotDriverAnalysisVariable(variable) {
return !isDriverAnalysisVariable(variable);
}
function addDriverAnalysisStamp(question) {
question.variables.forEach(function (variable) {
variable.name = preventDuplicateVariableName(variable.question.dataFile, variable.name + '_DriverAnalysis');
});
}
function checkVariablesAreFromSameDataFile(variables) {
if (variables.length < 2)
return true;
for (var i = 1; i < variables.length; i++) {
if (variables[i].question.dataFile.name != variables[0].question.dataFile.name) {
alert('Variables must be from the same data file.\n\nClick OK to reselect Variables or Cancel to stop the script.');
return false;
}
}
return true;
}
function createIndependentQuestion(independent_vars, dependent_var) {
var variable_exp = createExp(independent_vars, dependent_var);
var data_file = independent_vars[0].question.dataFile;
var variables_linked = [];
var v_linked = null;
var single_question = fromSameQuestion(independent_vars);
for (var i = 0; i < independent_vars.length; i++) {
var v = independent_vars[i];
var linked_name = preventDuplicateVariableName(data_file, v.name + '_L');
if (single_question)
var linked_label = v.label;
else
var linked_label = getQuestionNameAndVariableLabel(v);
v_linked = data_file.newJavaScriptVariable(variable_exp + v.name, false, linked_name,
linked_label, v_linked);
variables_linked.push(v_linked);
}
return data_file.setQuestion(createCompositeQuestionName(independent_vars), 'Number - Multi', variables_linked);
}
function createExp(independent_vars, dependent_var) {
var names = independent_vars.map(function (x) { return x.name; });
var dependent_data_file_name = dependent_var.question.dataFile.name;
if (independent_vars[0].question.dataFile.name == dependent_data_file_name)
names.push(dependent_var.name);
else {
var escaped_name = dependent_data_file_name.replace(/\'/g, "\\\'");
names.push('Q.GetValue(\'' + dependent_var.name + '\',\'' + escaped_name + '\')');
}
return 'if (isNaN(' + names.join(') || isNaN(') + '))\n NaN;\nelse\n ';
}
function createCompositeQuestionName(variables) {
var composite_name = '';
var last_question_name = '';
variables.forEach(function (variable) {
var this_question_name = variable.question.name;
if (last_question_name != this_question_name) {
if (last_question_name != '')
composite_name += '; ';
if (variable.question.variables.length == 1)
composite_name += this_question_name;
else
composite_name += this_question_name + ': ' + variable.label;
last_question_name = this_question_name;
} else
composite_name += ', ' + variable.label;
});
if (composite_name.length > 128)
composite_name = composite_name.substring(0, 128) + '...';
return preventDuplicateQuestionName(variables[0].question.dataFile, composite_name);
}
// The rule that gets attached to the driver analysis table.
// This rule is written for Q 4.8.7 and later.
function driverAnalysisRule() {
// Controls, not actually displayed, only used to pass parameters
var text_box_dep = form.newTextBox('dependentQuestionName');
var text_box_data_file = form.newTextBox('dependentDataFileName');
var text_box_data_file_id = form.newTextBox('dependentDataFileId');
var text_box_name = form.newTextBox('analysisName');
var text_box_indep = form.newTextBox('independentQuestionName');
// Extract parameters
var dependent_question_name = text_box_dep.getValue();
var dependent_question;
var data_file_id = text_box_data_file_id.getValue();
if (data_file_id != '' && project.getDataFileById) {
dependent_question = project.getDataFileById(data_file_id).getQuestionByName(dependent_question_name);
if (!dependent_question)
table.suppressOutput('The Question "' + dependent_question_name + '" could not be found. This may be because the Question has been renamed. This driver analysis has to be rerun from the Online Library.');
} else {
var data_file_name = text_box_data_file.getValue();
var data_files = project.dataFiles;
var is_data_file_found = false;
for (var i = 0; i < data_files.length; i++)
if (data_files[i].name == data_file_name) {
is_data_file_found = true;
dependent_question = project.getDataFileByName(data_file_name).getQuestionByName(dependent_question_name);
break;
}
if (!is_data_file_found)
table.suppressOutput('The data file "' + data_file_name + '" could not be found. This may be because the project has been updated. This driver analysis has to be rerun from the Online Library.');
if (!dependent_question)
table.suppressOutput('The Question "' + dependent_question_name + '" could not be found. This may be because the Question has been renamed. This driver analysis has to be rerun from the Online Library.');
}
var analysis_name = text_box_name.getValue();
var independent_question = table.blueQuestion;
// Check if suffixes should be added on the combo box to warn them of possible slow computations.
var kruskal_combo_label = 'Kruskal Importance';
var shapley_combo_label = 'Shapley Importance';
var slow_options = independent_question.variables.length > 15;
var slow_string = slow_options ? ' (slow, consider using Relative Importance instead)' : '';
if (slow_options) { // Add the suffixes to the combo box options if above limits, 15 for Kruskal or Shapley.
shapley_combo_label = shapley_combo_label + slow_string;
kruskal_combo_label = kruskal_combo_label + slow_string;
}
var default_combo = analysis_name;
if (['Kruskal Importance', 'Shapley Importance'].indexOf(analysis_name) > -1 && slow_options)
default_combo = analysis_name + slow_string;
// Control to select analysis type
if (form.setTranslation) { // Remove when Q 4.10 is stable
var combo_box_name = form.newComboBox('analysisNameComboBox', ['Linear Regression Coefficients', 'Contribution', 'Beta', kruskal_combo_label, shapley_combo_label, 'Relative Importance', 'Elasticity']);
combo_box_name.setDefault(default_combo);
form.setInputControls([combo_box_name]);
analysis_name = combo_box_name.getValue();
}
// Remove suffixes if they were used
if (analysis_name == kruskal_combo_label)
analysis_name = 'Kruskal Importance';
if (analysis_name == shapley_combo_label)
analysis_name = 'Shapley Importance';
if (form.setTranslation) { // Remove when Q 4.10 is stable
if (analysis_name == 'Elasticity')
form.setTranslation('Average', analysis_name);
else
form.setTranslation('Average', analysis_name + ' (%)');
form.setTranslation('Missing n', 'Raw ' + analysis_name);
}
var item_name = analysis_name + ' for ' + dependent_question.variables[0].label;
if (form.setItemName) // Remove when Q 4.10 is stable
form.setItemName(item_name);
form.setHeading('Driver Analysis');
form.setSummary(item_name);
// Check that dependent Question is valid
if (dependent_question.questionType != "Number")
table.suppressOutput('The Question type of the dependent Question for driver analysis has been changed. Please change it back to Number and double-click on the blank area to the left to refresh the output.');
// Check that independent Question in blue dropdown is valid
var independent_question_name = text_box_indep.getValue();
if (independent_question.name != independent_question_name)
table.suppressOutput('The independent Question (blue Question) for driver analysis cannot be changed. It needs to be "' + independent_question_name + '".');
if (independent_question.questionType != 'Number - Multi')
table.suppressOutput('The independent Question (blue Question) for driver analysis must be of type "Number - Multi".');
else if (independent_question.variables.length < 2)
table.suppressOutput('The independent Question (blue Question) for driver analysis must have two or more Variables.');
else if (analysis_name == 'Elasticity' && hasNonPositiveValues(independent_question.variables))
table.suppressOutput('The independent Question (blue Question) for elasticity must have non-negative data.');
else if (['Kruskal Importance', 'Shapley Importance'].indexOf(analysis_name) > -1 && independent_question.variables.length > 27)
table.suppressOutput('The independent Question (blue Question) for ' + analysis_name + ' has more than 27 Variables. ' +
'The analysis you have requested is not possible because it would take too long to compute. ' +
'Consider using Relative Importance instead of ' + analysis_name + ', as it will generally give similar results for large numbers of Variables.');
else {
// Settings for different driver analyses
var normalized_multiplier = 100;
var r_squared_name = 'rSquared';
var normalized_name, raw_name, min_value, max_value;
switch (analysis_name) {
case 'Linear Regression Coefficients':
normalized_name = 'importances';
raw_name = 'independentVarCoefs';
min_value = Number.NEGATIVE_INFINITY;
max_value = Number.POSITIVE_INFINITY;
break;
case 'Contribution':
normalized_name = 'contributions';
raw_name = 'contributionsRaw';
min_value = 0;
max_value = Number.POSITIVE_INFINITY;
break;
case 'Beta':
normalized_name = 'betasNormalized';
raw_name = 'betas';
min_value = Number.NEGATIVE_INFINITY;
max_value = Number.POSITIVE_INFINITY;
break;
case 'Kruskal Importance':
normalized_name = 'kruskalImportanceNormalized';
raw_name = 'kruskalImportance';
min_value = 0;
max_value = 1;
break;
case 'Shapley Importance':
normalized_name = 'shapleyImportanceNormalized';
raw_name = 'shapleyImportance';
min_value = 0;
max_value = 1;
break;
case 'Relative Importance':
normalized_name = 'relativeImportanceNormalized';
raw_name = 'relativeImportance';
min_value = 0;
max_value = 1;
break;
case 'Elasticity':
normalized_name = 'elasticity';
raw_name = 'elasticity';
min_value = Number.NEGATIVE_INFINITY;
max_value = Number.POSITIVE_INFINITY;
normalized_multiplier = 1;
r_squared_name = 'elasticityRSquared';
break;
default:
throw new Error('Unknown analysis name: ' + analysis_name);
}
// If table.brownQuestion is a string, questionType will return undefined and fall back to the string.
var brown_question_type = table.brownQuestion.questionType || table.brownQuestion;
if (brown_question_type != 'SUMMARY' && brown_question_type != 'Pick One' && brown_question_type != 'Pick Any' && brown_question_type != 'Date')
table.suppressOutput('Select SUMMARY or a Pick One, Pick Any or Date Question in the brown dropdown.');
else {
var invalid_stat_name = getInvalidSelectedStatistics();
if (invalid_stat_name != null && !table.forPlot)
table.suppressOutput('The statistic "' + invalid_stat_name + '" is not valid for this driver analysis. Unselect it from the table.');
else if (typeof right_table !== 'undefined' && right_table.statistics.length > 0)
table.suppressOutput('"Right" statistics are not valid for this driver analysis. Unselect them from the table.');
else if (typeof below_table !== 'undefined' && below_table.statistics.length > 0)
table.suppressOutput('"Below" statistics are not valid for this driver analysis. Unselect them from the table.');
else {
table.showMissingAs('');
table.hypothesisTestingEnabled = false;
var stat_ass = table.statisticalAssumptions;
var selected_stats = table.statistics;
var score_index = table.statistics.indexOf('Average');
var r_squared_index = table.rowIndex('R-Squared (%)');
var not_duplicate_rows = getNotDuplicateRows();
var z_score;
if (form.setTranslation && jStat) {
form.setTranslation('Base n', 'Lower Confidence Bound ' + (0.5 * stat_ass.overallSignificanceLevel));
form.setTranslation('Effective Base n', 'Upper Confidence Bound ' + (1 - 0.5 * stat_ass.overallSignificanceLevel));
z_score = jStat.normal(0, 1).inv(1 - 0.5 * stat_ass.overallSignificanceLevel);
} else
z_score = 1.96;
if (brown_question_type == 'SUMMARY')
fillSummaryTable();
else
fillCrosstab();
}
}
}
table.extraFooters = ['Dependent Variable: ' + dependent_question.variables[0].label];
function fillSummaryTable() {
var correction = table.statisticalAssumptions.cellMultipleComparisonCorrection;
var sig_level = table.statisticalAssumptions.overallSignificanceLevel;
var has_correction = correction != null;
var lin_reg = has_correction ? Q.linearRegression(dependent_question, [independent_question], correction, sig_level)
: Q.linearRegression(dependent_question, [independent_question]);
if (lin_reg.failed)
table.suppressOutput(lin_reg.failureMessage);
else {
setStatistic('Average', getNormalizedScores);
setStatistic('Missing n', getRawScores);
setStatistic('Standard Error', getStandardErrors);
setStatistic('Base n', getLowerConfidenceIntervals);
setStatistic('Effective Base n', getUpperConfidenceIntervals);
setStatistic('t-Statistic', getTStatistics);
setStatistic('z-Statistic', getZStatistics);
setStatistic('p', getPValues);
setStatistic('Corrected p', getCorrectedPValues);
setStatistic('Multiple Comparison Adjustment', getMultipleComparisonAdjustments);
setStatistic('Expected Average', getExpectedCoefficients);
if (table.forPlot)
addPercentSigns();
setProperty('cellSignificance', getSignificance);
setProperty('cellArrows', getArrows);
setProperty('cellFontColors', getFontColors);
}
// getValues is a function that takes a linear regression object
function setStatistic(stat_name, getValues) {
if (selected_stats.indexOf(stat_name) != -1) {
var new_values = getValues(lin_reg);
var table_values = table.get(stat_name);
var c = 0;
for (var i = 0; i < table.numberRows; i++)
if (not_duplicate_rows[i] == 0)
table_values[i][0] = NaN;
else { // only not duplicate rows are in new_values
table_values[i][0] = new_values[c];
c++;
}
if (stat_name == 'Average' && r_squared_index != -1)
table_values[r_squared_index] = [100 * lin_reg[r_squared_name]];
table.set(stat_name, table_values);
}
}
function setProperty(property_name, getValues) {
var table_values = table[property_name];
var new_values = getValues(lin_reg);
var c = 0;
for (var i = 0; i < table.numberRows; i++) {
if (not_duplicate_rows[i] == 0) {
if (property_name == 'cellSignificance')
table_values[i][0] = false;
} else {
table_values[i][0] = new_values[0][c];
c++;
}
}
table[property_name] = table_values;
}
function addPercentSigns() {
if (score_index != -1) {
var cell_texts = table.cellText;
if (analysis_name != 'Elasticity')
for (var i = 0; i < table.numberRows; i++)
if (not_duplicate_rows[i] == 1)
cell_texts[i][0] = ['%'];
if (r_squared_index != -1)
cell_texts[r_squared_index][0] = ['%'];
table.cellText = cell_texts;
}
}
function getNormalizedScores(lin_reg) { return lin_reg[normalized_name].map(function (x) { return normalized_multiplier * x; }); }
function getRawScores(lin_reg) { return lin_reg[raw_name]; }
function getStandardErrors(lin_reg) { return lin_reg[raw_name + 'StandardErrors']; }
function getLowerConfidenceIntervals(lin_reg) {
var raw_scores = getRawScores(lin_reg);
var standard_errors = getStandardErrors(lin_reg);
return raw_scores.map(function (x, index) { return Math.max(x - z_score * standard_errors[index], min_value)});
}
function getUpperConfidenceIntervals(lin_reg) {
var raw_scores = getRawScores(lin_reg);
var standard_errors = getStandardErrors(lin_reg);
return raw_scores.map(function (x, index) { return Math.min(x + z_score * standard_errors[index], max_value)});
}
function getTStatistics(lin_reg) { return lin_reg[raw_name + 'TStatistics']; }
function getZStatistics(lin_reg) { return lin_reg[raw_name + 'ZStatistics']; }
function getPValues(lin_reg) { return lin_reg[raw_name + 'PValues']; }
function getCorrectedPValues(lin_reg) { return lin_reg[raw_name + 'CorrectedPValues'].map(function (x) { return Math.min(x, 1); }); }
function getMultipleComparisonAdjustments(lin_reg) {
var p_values = getPValues(lin_reg);
return lin_reg[raw_name + 'CorrectedPValues'].map(function (x, index) { return x / p_values[index]; });
}
function getExpectedCoefficients(lin_reg) { return getNormalizedScores(lin_reg).map(function () { return 0; }); }
function getSignificance(lin_reg) { return stat_ass.significance([getCorrectedPValues(lin_reg)]); }
function getArrows(lin_reg) { return stat_ass.arrows([getCorrectedPValues(lin_reg)], [getTStatistics(lin_reg)]); }
function getFontColors(lin_reg) { return stat_ass.fontColors([getCorrectedPValues(lin_reg)], [getTStatistics(lin_reg)]); }
}
function limitWarnings(warnings, trimmed_suffix) {
var final_warnings = [];
var message_line_limit = 25;
var message_lines = 0;
var trimmed_warnings = 0;
warnings.forEach(function (warning) {
message_lines += (warning.match(/\n/g) || ['']).length; // count lines
if (final_warnings.length == 0 || message_lines < message_line_limit)
final_warnings.push(warning);
else
trimmed_warnings++;
});
if (trimmed_warnings > 0)
final_warnings.push('.. and ' + trimmed_warnings + trimmed_suffix);
return final_warnings.join('');
}
function fillCrosstab() {
var correction = table.statisticalAssumptions.cellMultipleComparisonCorrection;
var sig_level = table.statisticalAssumptions.overallSignificanceLevel;
var has_correction = correction != null;
var lin_reg_crosstab = has_correction ? Q.linearRegressionCrosstab(dependent_question, [independent_question], table.brownQuestion, correction, sig_level)
: Q.linearRegressionCrosstab(dependent_question, [independent_question], table.brownQuestion);
var failed_columns = [];
lin_reg_crosstab.failed.forEach(function (failed, index) {
if (lin_reg_crosstab.failed[index])
failed_columns.push('Column "' + lin_reg_crosstab.labels[index] + '" has no results:\n' +
// Indent each line of the failure message, because it is quite long.
lin_reg_crosstab.failureMessages[index].replace(/^/gm, ' ') + '\n');
});
if (failed_columns.length > 0)
alert(limitWarnings(failed_columns, ' more columns had no results.'));
setStatisticCrosstab('Average', getNormalizedScores);
setStatisticCrosstab('Missing n', getRawScores);
setStatisticCrosstab('Standard Error', getStandardErrors);
setStatisticCrosstab('Base n', getLowerConfidenceIntervals);
setStatisticCrosstab('Effective Base n', getUpperConfidenceIntervals);
setStatisticCrosstab('t-Statistic', getTStatistics);
setStatisticCrosstab('z-Statistic', getZStatistics);
setStatisticCrosstab('p', getPValues);
setStatisticCrosstab('Corrected p', getCorrectedPValues);
setStatisticCrosstab('Multiple Comparison Adjustment', getMultipleComparisonAdjustments);
if (table.forPlot)
addPercentSignsCrosstab();
setPropertyCrosstab('cellSignificance', getSignificance);
setPropertyCrosstab('cellArrows', getArrows);
setPropertyCrosstab('cellFontColors', getFontColors);
function setStatisticCrosstab(stat_name, getValues) {
if (selected_stats.indexOf(stat_name) != -1) {
var table_values = table.get(stat_name);
var new_values = getValues(lin_reg_crosstab);
for (var i = 0; i < table.numberColumns; i++) {
if (lin_reg_crosstab.failed[i]) {
for (var j = 0; j < table.numberRows; j++)
table_values[j][i] = NaN;
} else {
var c_row = 0;
for (var j = 0; j < table.numberRows; j++) {
if (not_duplicate_rows[j] == 0)
table_values[j][i] = NaN;
else { // only not duplicate rows are in new_values
table_values[j][i] = new_values[i][c_row];
c_row++;
}
}
if (stat_name == 'Average' && r_squared_index != -1)
table_values[r_squared_index][i] = 100 * lin_reg_crosstab[r_squared_name][i];
}
}
table.set(stat_name, table_values);
}
}
function setPropertyCrosstab(property_name, getValues) {
var table_values = table[property_name];
var new_values = getValues(lin_reg_crosstab);
for (var i = 0; i < table.numberColumns; i++) {
if (lin_reg_crosstab.failed[i]) {
if (property_name == 'cellSignificance')
for (var j = 0; j < table.numberRows; j++)
table_values[j][i] = false;
} else {
var c_row = 0;
for (var j = 0; j < table.numberRows; j++) {
if (not_duplicate_rows[j] == 0) {
if (property_name == 'cellSignificance')
table_values[j][i] = false;
} else { // only not duplicate rows are in new_values
table_values[j][i] = new_values[i][c_row];
c_row++;
}
}
}
}
table[property_name] = table_values;
}
function addPercentSignsCrosstab() {
if (score_index != -1) {
var cell_texts = table.cellText;
for (var i = 0; i < table.numberColumns; i++) {
if (!lin_reg_crosstab.failed[i]) {
if (analysis_name != 'Elasticity') {
for (var j = 0; j < table.numberRows; j++) {
if (not_duplicate_rows[j] == 1)
cell_texts[j][i] = ['%'];
}
}
if (r_squared_index != -1)
cell_texts[r_squared_index][i] = ['%'];
}
}
table.cellText = cell_texts;
}
}
function mapJagged(jagged_array, func) {
return jagged_array.map(function (x) {
if (x != null) {
return x.map(function (y) {
return func(y);
});
} else
return null;
});
}
function mapTwoJagged(jagged_array_1, jagged_array_2, func) {
return jagged_array_1.map(function (x, index_1) {
if (x != null) {
return x.map(function (y, index_2) {
return func(y, jagged_array_2[index_1][index_2]);
});
} else
return null;
});
}
function getNormalizedScores(lin_reg) { return mapJagged(lin_reg[normalized_name], function (x) { return normalized_multiplier * x; }); }
function getRawScores(lin_reg) { return lin_reg[raw_name]; }
function getStandardErrors(lin_reg) { return lin_reg[raw_name + 'StandardErrors']; }
function getLowerConfidenceIntervals(lin_reg) { return mapTwoJagged(getRawScores(lin_reg), getStandardErrors(lin_reg),
function (x, y) { return Math.max(x - z_score * y, min_value); }); }
function getUpperConfidenceIntervals(lin_reg) { return mapTwoJagged(getRawScores(lin_reg), getStandardErrors(lin_reg),
function (x, y) { return Math.min(x + z_score * y, max_value); }); }
function getTStatistics(lin_reg) { return lin_reg[raw_name + 'TStatistics']; }
function getZStatistics(lin_reg) { return lin_reg[raw_name + 'ZStatistics']; }
function getPValues(lin_reg) { return lin_reg[raw_name + 'PValues']; }
function getCorrectedPValues(lin_reg) { return mapJagged(lin_reg[raw_name + 'CorrectedPValues'], function (x) { return Math.min(x, 1); }); }
function getMultipleComparisonAdjustments(lin_reg) { return mapTwoJagged(getPValues(lin_reg), lin_reg[raw_name + 'CorrectedPValues'],
function (x, y) { return y / x; }); }
function getSignificance(lin_reg) { return stat_ass.significance(getCorrectedPValues(lin_reg)); }
function getArrows(lin_reg) { return stat_ass.arrows(getCorrectedPValues(lin_reg), getTStatistics(lin_reg)); }
function getFontColors(lin_reg) { return stat_ass.fontColors(getCorrectedPValues(lin_reg), getTStatistics(lin_reg)); }
}
function getNotDuplicateRows() {
var not_duplicate = table.get('Not Duplicate');
var results = [];
for (var i = 0; i < table.numberRows; i++)
for (var j = 0; j < table.numberColumns; j++) {
if (not_duplicate[i][j] == 1) {
results.push(1);
break;
}
if (j == table.numberColumns - 1)
results.push(0); // only run if all cells in the row are duplicate
}
return results;
}
function getInvalidSelectedStatistics() {
var valid_stats = ['Average', 'Missing n', 'Standard Error', 'Base n', 'Effective Base n', 't-Statistic', 'z-Statistic',
'p', 'Corrected p', 'Multiple Comparison Adjustment', 'Not Duplicate', 'Expected Average', 'Column n', 'Column Population'];
var selected_stats = table.statistics;
for (var i = 0; i < selected_stats.length; i++)
if (valid_stats.indexOf(selected_stats[i]) == -1)
return selected_stats[i];
return null;
}
function hasNonPositiveValues(variables) {
for (var i = 0; i < variables.length; i++) {
var variable = variables[i];
if (variable.question.questionType == 'Pick Any' || variable.question.questionType == 'Pick Any - Grid')
return true; // assume has 0 and 1
else {
var raw_values = variable.rawValues;
var value_attributes = variable.valueAttributes;
for (var j = 0; j < raw_values.length; j++)
if (value_attributes.getValue(raw_values[j]) <= 0)
return true;
}
}
return false;
}
}
See also
- Regression - Legacy Driver Analysis - Table of Linear Regression Coefficients
- Regression - Legacy Driver Analysis - Table of Contribution Scores
- Regression - Legacy Driver Analysis - Table of Beta Scores
- Regression - Legacy Driver Analysis - Table of Kruskal Importance Scores
- Regression - Legacy Driver Analysis - Table of Shapley Importance Scores
- Regression - Legacy Driver Analysis - Table of Relative Weights (Relative Importance Analysis)
- Regression - Legacy Driver Analysis - Table of Elasticity Scores
Further reading: Key Driver Analysis Software