Plot/Chart - Scatterplot from 2 Tables

From Q
Jump to navigation Jump to search

This QScript creates a scatter plot showing the data from two separate tables, where:

  • Each of the tables contains a single column of numbers.
  • The row labels of the tables match exactly in terms of text and case.

These tables need to be created prior to trying to create the scatterplot.

Example

The example below shows a performance-importance plot (sometimes called a quad-map), where the performance is SUMMARY of a Pick Any question, and the importance has been measured using Regression - Driver (Importance) Analysis - Shapley.

Scatterplot.png

Technical details

  • The script requests the user to select two tables. Each table must have a single column, consisting of numbers, and have common row labels. You are notified about row labels that only appear in one of the two tables. A scatterplot is created using the numbers extracted from the common rows.
  • The scatterplot will be created from static data copied from the selected tables. Any subsequent changes to those tables (i.e. data updates, recoding, changing filters and weights) will not be reflected in the scatterplot. The script has to be rerun in order to obtain an updated chart.
  • This QScript requires Q 4.9 or later.

How to apply this QScript

  • Start typing the name of the QScript into the Search features and data box in the top right of the Q window.
  • Click on the QScript when it appears in the QScripts and Rules section of the search results.

OR

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

Customizing the QScript

This QScript is written in JavaScript and can be customized by copying and modifying the JavaScript.

Customizing QScripts in Q4.11 and more recent versions

  • Start typing the name of the QScript into the Search features and data box in the top right of the Q window.
  • Hover your mouse over the QScript when it appears in the QScripts and Rules section of the search results.
  • Press Edit a Copy (bottom-left corner of the preview).
  • Modify the JavaScript (see QScripts for more detail on this).
  • Either:
    • Run the QScript, by pressing the blue triangle button.
    • Save the QScript and run it at a later time, using Automate > Run QScript (Macro) from File.

Customizing QScripts in older versions

  • Copy the JavaScript shown on this page.
  • Create a new text file, giving it a file extension of .QScript. See here for more information about how to do this.
  • Modify the JavaScript (see QScripts for more detail on this).
  • Run the file using Automate > Run QScript (Macro) from File.

JavaScript

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 table_array = [];
    var group_item = project.report;
 
    // Select importance and performance tables
    while (true) {
        var 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)
        {
            alert("There are no valid tables in your project. Try importing a data set and creating a table from the variables in the data set.")
            return false;
        }
        var output_importance = table_importance.calculateOutput();
        if (checkTableHasSingleColumnOfNumbers(output_importance, 'x-axis'))
            break;
    }
    while (true) {
        var table_performance = selectOneTableWithGroupNames('Select the table containing the data to show in the vertical coordinates (i.e., the y-axis):', group_item);
        var output_performance = table_performance.calculateOutput();
        if (checkTableHasSingleColumnOfNumbers(output_performance, 'y-axis'))
            break;
    }

    var labels_importance = difference(output_importance.rowLabels, ['R-Squared', 'SUM']);
    var labels_performance = difference(output_performance.rowLabels, ['R-Squared', 'SUM']);
    var labels_common = intersection(labels_importance, labels_performance);
    if (labels_common.length > 0) {
        alertIfMeasurementsMissing(labels_importance, labels_performance, 'y-axis');
        alertIfMeasurementsMissing(labels_performance, labels_importance, 'x-axis');
    } else {
        alert('There are no common rows between the two selected tables.');
        return false;
    }
 
    // Extract values from common rows of both tables
    var importances_all = output_importance.get(output_importance.statistics[0]);
    var performances_all = output_performance.get(output_performance.statistics[0]);
    var importances = [];
    var performances = [];
 
    for (var i = 0; i < labels_common.length; i++) {
        importances.push(importances_all[output_importance.rowIndex(labels_common[i])]);
        performances.push(performances_all[output_performance.rowIndex(labels_common[i])]);
    }
 
    // Create blue question containing variable labels
    var data_file = project.dataFiles[0];
    var row_labels_variable_name = preventDuplicateVariableName(data_file, 'variable_labels');
    var row_labels_variable = data_file.newJavaScriptVariable('Math.floor(Math.random()*' + labels_common.length +')', false, row_labels_variable_name, 'Scatterplot (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 xy_variable_name = preventDuplicateVariableName(data_file, 'labels_scatter_plot');
    var xy_variable = data_file.newJavaScriptVariable('Math.floor(Math.random()*2)', false, xy_variable_name, 'Scatterplot(brown)', null);
    xy_variable.variableType = 'Categorical';
    xy_variable.valueAttributes.setLabel(0, table_importance.name);
    xy_variable.valueAttributes.setLabel(1, table_performance.name);
 
    // Create scatte plot
    var plot = group_item.appendPlot('Scatterplot');
    plot.primary = row_labels_variable.question;
    plot.secondary = xy_variable.question;
    plot.name = 'Scatterplot: ' + table_importance.name + ' vs ' + table_performance.name;
    var expression = "stats = table.get('Column %');\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 += "table.set('Column %',stats);";
    addTableJavaScriptToTablesInArray([plot], expression);
 
    alert('The scatterplot 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;
}

See also