This function replaces specified missing codes in a data frame with NA values based on a given variable codebook.
Usage
ReplaceMissingCode(
data,
codebook,
DataFrame = lifecycle::deprecated(),
VariableCodebook = lifecycle::deprecated()
)Arguments
- data
A data frame containing the data.
- codebook
A data frame containing the variable codebook. It must have columns
VariableandMissingCode.Variablenames the column indata;MissingCodeholds the code, or several codes separated by commas or semicolons, to replace withNA. Rows with a missing or blankMissingCodeare skipped.- DataFrame
Deprecated (since 19.15.0). Use
datainstead.- VariableCodebook
Deprecated (since 19.15.0). Use
codebookinstead.
Details
Study databases rarely leave missing values empty. They record why the
value is missing, using sentinel numbers outside the plausible range - -7
for "not applicable", -8 for "refused", -9 for "not asked", 999 for
"unknown". Left in place, those codes are read as real measurements: a mean
age climbs into the hundreds, and a variable coded -7/-8 gets a negative
mean that no one notices until much later.
This converts every code listed in the codebook to NA, so the values are
excluded from statistics and counted as missing.
Several markers for one variable
A variable usually has more than one missing code, since the whole point of
sentinels is to distinguish reasons. List them all in a single
MissingCode cell, separated by commas or semicolons:
Whitespace around the separators is ignored, so -7,-8 and -7, -8 behave
identically. When a codebook is assembled in R rather than read from a
spreadsheet, MissingCode may also be a list-column of vectors.
Codes are matched on the column's own scale: numerically for numeric
columns, and as text for character and factor columns, so markers like
"Refused" or "Unknown" work. When such a marker is a factor level, the
level is removed along with the values, so it does not linger as an empty
category in later tables.
Variables whose MissingCode is blank are left untouched, and a codebook
naming variables that are not in data warns rather than failing - a
codebook usually describes more columns than any one analysis selects.
See also
CreateVariableTypesTemplate(), which generates a codebook with a
MissingCode column ready to fill in, and RevalueData(), which applies
missing codes as part of the full relabelling workflow.
Examples
# `age` uses three different codes to record three different reasons
df <- data.frame(
id = 1:6,
age = c(34, 999, 52, -7, 41, -8),
score = c(10, -9, -9, 15, 20, 12),
status = c("Active", "Unknown", "Active", "Withdrawn", "Unknown", "Active")
)
# Several markers for one variable go in one cell
codebook <- data.frame(
Variable = c("age", "score", "status"),
MissingCode = c("999, -7, -8", "-9", "Unknown")
)
# Before: the sentinels are averaged in as if they were ages
df
#> id age score status
#> 1 1 34 10 Active
#> 2 2 999 -9 Unknown
#> 3 3 52 -9 Active
#> 4 4 -7 15 Withdrawn
#> 5 5 41 20 Unknown
#> 6 6 -8 12 Active
mean(df$age)
#> [1] 185.1667
# After: every listed code becomes NA
cleaned <- ReplaceMissingCode(df, codebook)
cleaned
#> id age score status
#> 1 1 34 10 Active
#> 2 2 NA NA <NA>
#> 3 3 52 NA Active
#> 4 4 NA 15 Withdrawn
#> 5 5 41 20 <NA>
#> 6 6 NA 12 Active
mean(cleaned$age, na.rm = TRUE)
#> [1] 42.33333
colSums(is.na(cleaned))
#> id age score status
#> 0 3 2 2
# Blank codes are skipped
ReplaceMissingCode(
df,
data.frame(Variable = c("id", "age"), MissingCode = c(NA, "999, -7, -8"))
)
#> id age score status
#> 1 1 34 10 Active
#> 2 2 NA -9 Unknown
#> 3 3 52 -9 Active
#> 4 4 NA 15 Withdrawn
#> 5 5 41 20 Unknown
#> 6 6 NA 12 Active
