Modify Cell Content - Remove Decimals Without Rounding

From Q
Jump to: navigation, search

This rule modified the selected statistics to remove the decimal places after a certain number without rounding the numbers. Unlike various rounding procedures this does not change the last decimal place.


In this example, the Average has been selected as the statistic to modify, and the number of decimal places chosen is 1. All decimal places after the first now show zeros. Note that unlike other rounding procedures, this does not change the decimal place that has been kept (that is, the first decimal place).


Technical details

Significance tests are conducted on the results prior to the modification.

You can choose to modify all numeric statistics shown on the table, or you can select a set of statistics to modify.

You can also choose whether or not marginal statistics (Statistics - Below and Statistics - Right) are included in the modification.

A foot note is added to explain which statistics have been modified in this way.

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.


  • 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).


includeWeb('Table JavaScript Utility Functions');
// List of statistics for the menu. Text-based stats, or stats which are
// already integers (eg Base n) are not included.
var not_selected_string = "(none)";
var stat_list = [not_selected_string].concat(_GLOBAL_STAT_LIST);

var stats_to_remove =  ["Base n", "Column n", "Column Comparisons",
                        "Column Names", 
                        "Columns Compared", "Expected n", "Missing n", "n",
                        "n Observations", "Not duplicate", "Row n", "Text",
                        "Text With No Blanks", "Unique Text"];

stat_list = stat_list.filter(function (s) { return stats_to_remove.indexOf(s) == -1; });
// Decimal number control
var decimals_label = form.newLabel("Decimal places to keep: ");
var decimals_box = form.newNumericUpDown("nd");
decimals_box.lineBreakAfter = true;
// Apply to marginal statistics?
var marginals_check_box = form.newCheckBox("mcb", "Apply to marginal statistics");
marginals_check_box.lineBreakAfter = true;
// Apply to all statistics?
var all_stats_box = form.newCheckBox("ascb", "Apply to all statistics");
all_stats_box.lineBreakAfter = true;

var controls = [decimals_label, decimals_box, marginals_check_box, all_stats_box];
var all_stats = all_stats_box.getValue(); 
var num_decimals = decimals_box.getValue();
var do_marginals = marginals_check_box.getValue();
var all_selected_stats = table.statistics;
if (do_marginals) {
    if (rightTableExists())
        all_selected_stats = all_selected_stats.concat(right_table.statistics);
    if (belowTableExists())
        all_selected_stats = all_selected_stats.concat(below_table.statistics);
// If not applying to all stats then get the user to select which stats to use
var stats = [];
if (!all_stats) {
    var stat_select_label = form.newLabel("Apply only to:");
    stat_select_label.lineBreakAfter = true;
    var counter = 0;
    var new_stat_box, last_selection;

    var make_new_stat_box = function () {
        new_stat_box = form.newComboBox("sb" + counter, stat_list);
        new_stat_box.lineBreakAfter = true;
        last_selection = new_stat_box.getValue();


    while (last_selection != not_selected_string) {
        counter ++;
} else
    stats = all_selected_stats;
// Create messages to use in summary and footer 
var decimals_string = num_decimals + " decimal place" + (num_decimals == 1 ? "" : "s");
var summary_text = "Remove decimals (without rounding) after " + decimals_string + ": " 
                    + (all_stats ? "all statistics" : stats.slice(0, Math.min(3, stats.length)).join(", ") + (stats.length > 3 ? "..." : ""));
form.setHeading("Remove Decimals Without Rounding");
// Change table stats

truncateTable(table, function (stat, truncated_stats) {
    table.set(stat, truncated_stats);

if (do_marginals) {
    if (rightTableExists()) {
        truncateTable(right_table, function (stat, truncated_stats) {
            setMarginalStatistic(right_table, stat, truncated_stats);
    if (belowTableExists()) {
        truncateTable(below_table, function (stat, truncated_stats) {
            setMarginalStatistic(below_table, stat, truncated_stats);

// Set footer
var trimmed_stats = stats.filter(function (s) { return all_selected_stats.indexOf(s) > -1 });
if (all_stats || trimmed_stats.length > 0) {
    var footer = table.extraFooters;
    var footer_message = (all_stats ? "All statistics" : trimmed_stats.join(", ")) 
                         + " have decimals removed after " + decimals_string;
    table.extraFooters = footer;

// For each selected statistic, get its values, truncate them, and then
// fire a function that decides how to apply them to the table.
// apply_truncated_stats should be a function(stat, 2d_stats_array) {}
function truncateTable(ttable, apply_truncated_stats) {
    ttable.statistics.forEach(function (stat) {
        if (stats.indexOf(stat) > -1) {
            var current_values = ttable.get(stat);
            if (typeof current_values[0][0] != "string") {
                apply_truncated_stats(stat, truncateStats(current_values, num_decimals));

// Truncate the number to a certain number of decimal places
// by converting the number to a string, cutting the number
// of decimals, then converting back to a float.
function truncateDecimalNumber(x, num_decimals) {
    if (isNaN(x) || x == 0)
        return x;
    var num_string = x.toPrecision(13); // Q rounds the raw numbers to 13 decimal places
    var split_string = num_string.split(".");
    var new_string = split_string[0] + "." + split_string[1].substr(0, num_decimals);
    return parseFloat(new_string);

// Truncate the whole array of stats. array should be in the shape of a Q table.
function truncateStats(array, num_decimals) {
    if (num_decimals !== parseInt(num_decimals, 10))
        throw new Error("Expected an integer value.");
    if (num_decimals < 0)
        throw new Error("Expected a non-negative value.");

    var new_values = (a) {
        return (b) {
            return truncateDecimalNumber(b, num_decimals);
    return new_values;

See also