The tables should be created prior to creating the Bubble plot.
The first table selected defines the data for the horizontal dimension (x-axis), the second table defines the data for the vertical dimension (y-axis), and the third table defines the data that is used to determine the size of the bubbles.
includeWeb('QScript Table Functions');
includeWeb('QScript Utility Functions');
includeWeb('QScript Selection Functions');
includeWeb('JavaScript Array Functions');
var version = fileFormatVersion();
if (version < 8.39) {
log('This script is not able to run on this version of Q. Please upgrade to the latest version of Q.');
} else if (!main()) {
log('QScript was cancelled.');
}
function main() {
var group_item = project.report;
var table_importance, output_importance;
while (true) {
table_importance = selectOneTableWithGroupNames('Select the table containing the data to show in the horizontal coordinates (i.e., the x-axis):', group_item);
if (table_importance.length == 0) {
log("There are no tables in your document to create a plot.");
return false;
}
output_importance = table_importance.calculateOutput();
if (checkTableHasSingleColumnOfNumbers(output_importance, 'x-axis'))
break;
}
var table_performance, output_performance;
while (true) {
table_performance = selectOneTableWithGroupNames('Select the table containing the data to show in the vertical coordinates (i.e., the y-axis):', group_item);
output_performance = table_performance.calculateOutput();
if (checkTableHasSingleColumnOfNumbers(output_performance, 'y-axis'))
break;
}
var table_bubble, output_bubble;
while (true) {
table_bubble = selectOneTableWithGroupNames('Select the table containing the data to determine the bubble sizes:', group_item);
output_bubble = table_bubble.calculateOutput();
if (checkTableHasSingleColumnOfNumbers(output_bubble, 'bubble size'))
break;
}
// Obtain row labels from tables
var labels_importance = output_importance.rowLabels;
var labels_performance = output_performance.rowLabels;
var labels_bubble = output_bubble.rowLabels;
// Remove labels corresponding to original NET rows
if (output_importance.netRows) {
function descendingSorter(a,b) { return b - a; }
var importance_nets = output_importance.netRows.sort(descendingSorter);
var performance_nets = output_performance.netRows.sort(descendingSorter);
var bubble_nets = output_bubble.netRows.sort(descendingSorter);
importance_nets.forEach(function (x) {
labels_importance.splice(x, 1);
});
performance_nets.forEach(function (x) {
labels_performance.splice(x, 1);
});
bubble_nets.forEach(function (x) {
labels_bubble.splice(x, 1);
});
}
// Figure out which labels are common to all
var exclude_labels = ['R-Squared', 'SUM', 'NET'];
labels_importance = difference(labels_importance, exclude_labels);
labels_performance = difference(labels_performance, exclude_labels);
labels_bubble = difference(labels_bubble, exclude_labels);
var labels_common = intersection(intersection(labels_importance, labels_performance), labels_bubble);
// Alert the user to those labels that are not common in the 3 tables
if (labels_common.length > 0) {
alertIfMeasurementsMissing(labels_importance, labels_common, 'x-axis');
alertIfMeasurementsMissing(labels_performance, labels_common, 'y-axis');
alertIfMeasurementsMissing(labels_bubble, labels_common, 'bubble size');
} else {
alert('There are no common rows between the selected tables.');
return false;
}
// Extract values from common rows of all tables
var importances_all = output_importance.get(output_importance.statistics[0]);
var performances_all = output_performance.get(output_performance.statistics[0]);
var bubbles_all = output_bubble.get(output_bubble.statistics[0]);
var importances = [];
var performances = [];
var bubbles = [];
labels_common.forEach(function (label, index) {
importances.push(importances_all[output_importance.rowIndex(label)]);
performances.push(performances_all[output_performance.rowIndex(label)]);
bubbles.push(bubbles_all[output_bubble.rowIndex(label)]);
});
// Create blue question containing variable labels
var data_file = project.dataFiles[0];
var row_labels_variable_name = preventDuplicateVariableName(data_file, 'variable_labels');
// We need the variable's results to contain all the unqiue categorical values.
// Rely on Math.random() to mostly evenly distribute the values across all respondents.
// We could also generate a sequence using the respondents' order in the data file,
// but we cannot set "Access all data rows" in QScript.
var row_labels_variable = data_file.newJavaScriptVariable('Math.floor(Math.random()*' + labels_common.length +')', false, row_labels_variable_name, 'Bubble plot (blue)', null);
row_labels_variable.variableType = 'Categorical';
for (var i = 0; i < labels_common.length; i++)
row_labels_variable.valueAttributes.setLabel(i, labels_common[i]);
// Create brown question containing the labels that correspond to the input tables'
var xyz_variable_name = preventDuplicateVariableName(data_file, 'labels_scatter_plot');
var xyz_variable = data_file.newJavaScriptVariable('Math.floor(Math.random()*3)', false, xyz_variable_name, 'Bubble plot (brown)', null);
xyz_variable.variableType = 'Categorical';
xyz_variable.valueAttributes.setLabel(0, table_importance.name);
xyz_variable.valueAttributes.setLabel(1, table_performance.name);
xyz_variable.valueAttributes.setLabel(2, table_bubble.name);
// Create plot
var plot = group_item.appendPlot('Bubble plot');
plot.primary = row_labels_variable.question;
plot.secondary = xyz_variable.question;
plot.name = 'Bubble plot: ' + table_importance.name + ' vs ' + table_performance.name + ' vs ' + table_bubble.name + ' (bubble size)';
var expression = "includeWeb('Table JavaScript Utility Functions');\r\n"
+ "var rule_name = '" + plot.name + "';\r\n"
+ "form.setSummary(rule_name);\r\n"
+ "requireNumericTableDimensionsStatistics(['Column %'], " + labels_common.length + ", 3, false, rule_name);\r\n"
+ "stats = table.get('Column %');\r\n";
for (var i = 0; i < labels_common.length; i++) {
expression += "stats[" + i + "][0] = " + importances[i] + ";\n";
expression += "stats[" + i + "][1] = " + performances[i] + ";\n";
expression += "stats[" + i + "][2] = " + bubbles[i] + ";\n";
}
expression += "table.set('Column %', stats)";
addTableJavaScriptToTablesInArray([plot], expression);
alert('The bubble plot will be created from static data copied from the two tables. ' +
'Any subsequent changes to the input tables (i.e. changing filters and weights) will not be reflected in the scatterplot.');
log('A plot named "' + plot.name + '" has been added to the project.');
return true;
}