Skip to contents

A rating scale (Likert / rating item) has a small set of consecutive valid integer levels. Any value outside that set is a data problem, and this check both flags it and, for each value, offers the most likely explanation:

  • a missing-data code left as a number (a -99 / 999 in the sentinel list, or a codebook-declared missing code) – recode to NA;

  • a keying typo of an in-scale value (a 33 for 3, a 55 for 5) – the probable intended value is named;

  • otherwise an unexplained out-of-range value to review.

The valid range is ground truth when valid_values / valid_range are supplied (e.g. from a codebook), otherwise inferred by .detect_likert_scale. A column that is not a rating scale (continuous, many-level, non-integer, too few rows) has no fixed range and is not flagged here – unbounded variables (age, reaction time) have no principled "valid range" to violate.

Usage

data_check_scale_values(
  x,
  sentinels = .data_missing_sentinels,
  declared = NULL,
  valid_values = NULL,
  valid_range = NULL,
  n_max = 10,
  min_ground_truth_coverage = 0.5,
  infer = TRUE
)

Arguments

x

a numeric vector

sentinels

candidate missing-data sentinel codes

declared

optional codebook-declared missing codes (ground truth)

valid_values

optional enumerated valid codes (ground truth)

valid_range

optional c(lo, hi) valid range (ground truth)

n_max

max number of values to list in the message

min_ground_truth_coverage

minimum fraction of non-missing values that must already fall inside a declared valid_values/valid_range for it to be trusted; below this, ground truth is discarded in favour of inference

infer

if TRUE (default), infer a rating-scale range from the data when no ground truth is supplied or it was discarded; if FALSE, flag nothing in that case. codebook_check uses FALSE: it reports only values outside a range the authors documented, never a guessed one.

Value

list(problem, message, values, lower, upper, classes) where classes labels each flagged value "missing", "typo:<intended>", or "unexplained"

Details

Ground truth is trusted only when it is actually PLAUSIBLE for this column's data: at least min_ground_truth_coverage of the non-missing values must already fall inside the declared range. A codebook/.qsf variable can be mismatched to the wrong data column (a cross-study name collision, or a Qualtrics timing/paradata column inheriting its question's response codes – see the .qsf question-tag fallback in match_column_labels()); when that happens the declared range explains almost none of the data, and trusting it anyway turns nearly every real value into a false "out of range" flag. When coverage is too low, ground truth is DISCARDED for this column (not merely widened) and the range falls back to .detect_likert_scale inference, same as if no ground truth had been supplied at all – or, with infer = FALSE, nothing is flagged for the column.

This unifies the former data_check_out_of_range and data_check_miscoded_missing: one detector run, one finding per column.

Author

Daniel Lakens and Levi Baruch

Examples

# a 7-point scale with two values outside it
data_check_scale_values(c(rep(1:7, 7), 99, 33))$message
#> [1] "2 values outside the 1-7 scale: 33 (looks like a typo of 3), 99 (looks like a missing-data code -> recode to NA)"