Reversed and Offset Code Means

A common issue is a rating scale collected as 1=worst, 10=best, but for analysis and stats purposes you want 1=best, 10=worst. Similarly, the data collection may have been 1=none, 2=worst, 11=best, but you want 0=none, 10=best.

In Quantum and some other systems, these circumstances are covered by factors. Ruby does not yet have direct support for factors. Our design position was that since codes can be positive or negative integers or floats, most of time when factors are needed, the codes can do the same job with less complexity. But this won’t help for reversed or offset rating scales.

One approach is to exploit a mathematical property of code means, namely that the code mean is linear to the low and high bounds. If the code mean of codes 1 to 10 is 6.63, then the code mean of 11 to 20, where frequency-wise code 1 = code 11, code 10 = code 20, is 10+6.63 = 16.63.

To verify this (using the Demo job variable NPS_1), create a temporary construction which maps 1->11,…10->20 as

Then run the table Count by NPS_1, temp, with code means on both. The table is

This property of code means can be exploited to reverse and offset. The following table verifies the straight, reversed and offset code means from first principles.

However, the sneaky trick of reversing a code mean by highbound+1-cmn has a problem if the operands are all zero or empty, as this table shows:

Since all the males are filtered out, the highlighted values should be *, meaning ‘cannot calculate’ too, but they show instead as 11 and -1 because Ruby expression evaluation always treats missing as zero if possible, so for the Males column 11-cmn = 11-missing = 11-0 = 11. Most of the time, treating missing as zero is very convenient, and gives you what you would want, but here it doesn’t.

If there is a chance of an empty column, you can either use the long forms c1*10+…c10*1, or make the expression conditional by dividing by a boolean, as #(11-cmn)/(cmn>0). An empty column now evaluates to *=missing:

This is effectively an if…then…else:  If cmn > 0 then (11-cmn)/true = (11-cmn)/1 = 11-cmn Else (11-cmn)/false = (11-cmn)/0 = missing.

Another approach is to construct a new variable which maps the original codes to the factors. The fast way to do this is to use DefMap – that is, define a one-to-one code mapping. Say I want to (for some crazy reason) map Gender codes 1/2 as 10.5 and 218.336. The DefMap is

DefMap “myfactorvar”, “Gender”, “1=10.5;2=218.336”, “Map codes to Factors”
Construct “myfactorvar”

The output is

And a table showing some of the code stats is