Imputes missing values from the k nearest complete observations.
Numeric and factor variables are both supported.
Usage
imputeKnn(
x,
k = 10,
scale = TRUE,
method = c("weighted", "median"),
distData = NULL
)Arguments
- x
a data frame with missing values.
- k
positive integer, the number of nearest neighbours to draw on.
- scale
logical; if
TRUE(default), numeric variables are standardized before distances are computed. This affects the distances only, not the imputed values.- method
the aggregation applied to the neighbours' values, either
"weighted"for a distance-weighted mean (numeric) or weighted mode (factor), or"median"for a median (numeric) or mode (factor).- distData
optional data frame supplying the pool of potential neighbours. If given, neighbours are drawn from
distDataonly, whilexalone is imputed. It must have the same variables asx.
Details
Distance is Gower-style: numeric variables contribute their squared
differences and factor variables a 0/1 mismatch penalty, summed and
square-rooted. Numeric variables are standardized beforehand when
scale = TRUE, so that no variable dominates through its unit
alone. The standardization affects distances only; imputed values are
always taken from the original data.
Continuous and categorical contributions are combined without further weighting, so a factor mismatch counts as much as a one-standard-deviation numeric gap. Whether that balance suits the data is for the caller to judge.
Each incomplete observation is compared with the complete ones on the variables it does observe, so rows missing different variables use different distances. Observations are therefore grouped by their pattern of missingness and each pattern is solved in one pass.
With method = "weighted" the neighbours are weighted by
\(\exp(-d)\). Because that decays on the scale of the distances
themselves, it is meaningful only when those are of moderate size, which
is another reason to keep scale = TRUE. Weights are normalized
against their maximum before exponentiation, so that widely separated
neighbours cannot all underflow to zero.
When dbscan is installed it is used to find the neighbours via a kd-tree, which is markedly faster on large data. The result is the same either way, apart from the resolution of exact ties.
See also
Other impute:
impute()
Examples
set.seed(123)
dat <- data.frame(
x = c(1, 2, 3, 4, 5, 6),
y = c(1, 2, 3, 4, 5, 6),
z = factor(c("a", "b", "a", "b", "a", "b"))
)
dat[c(1, 3), "x"] <- NA
dat[c(2, 5), "y"] <- NA
imputeKnn(dat, k = 2)
#> x y z
#> 1 4.599849 1.00000 a
#> 2 2.000000 4.47332 b
#> 3 4.688363 3.00000 a
#> 4 4.000000 4.00000 b
#> 5 5.000000 5.00000 a
#> 6 6.000000 6.00000 b
# neighbours drawn from a separate reference set
ref <- data.frame(
x = c(1.5, 2.5, 3.5, 4.5),
y = c(1.5, 2.5, 3.5, 4.5),
z = factor(c("a", "b", "a", "b"), levels = c("a", "b"))
)
imputeKnn(dat, k = 2, distData = ref)
#> x y z
#> 1 1.758634 1.000000 a
#> 2 2.000000 2.174485 b
#> 3 2.798218 3.000000 a
#> 4 4.000000 4.000000 b
#> 5 5.000000 3.978892 a
#> 6 6.000000 6.000000 b
