Вменяйте пропущенные значения со значением ROLLING в R
Я новичок в R и борюсь с проблемой.
Мне нужна функция для вычисления отсутствующих значений в векторе в соответствии со средним значением элементов в окне заданного размера.
Тем не менее, это окно будет двигаться, потому что, скажем, мой NA
находится в положении 30, а мой размер окна 10, среднее значение должно быть рассчитано для x[20:40]
, Так что для каждого найденного NA
Окно значит будет другим.
Я пытался это:
impute.to.window.mean <- function(x, window) {
na.idx <- is.na(x) #find missing values in x
for (na in na.idx) {
y <- (x[na]-window):(x[na]+window)
na.idx[na] <- mean(y, na.rm = TRUE)
}
return(x)
}
но это не правильно, и я не знаю, как продолжить.
5 ответов
Вы можете рассмотреть возможность использования imputeTS
пакет. Вот пример заполнения значений простой скользящей средней и окном 4:
x <- rnorm(100)
x[c(7, 21, 33)] <- NA
imputeTS::na.ma(x, k = 4, weighting = "simple")
Используя zoo::rollapply, это можно сделать одним оператором. Мы использовали окно длиной 5 (2 по обе стороны от текущей точки) для этого примера:
library(zoo)
x <- replace(1:20, c(4, 6, 10, 15), NA) # test data
rollapply(c(NA, NA, x, NA, NA), 5,
function(x) if (is.na(x[3])) mean(x, na.rm = TRUE) else x[3])
давая:
[1] 1.000000 2.000000 3.000000 3.333333 5.000000 6.666667 7.000000
[8] 8.000000 9.000000 10.000000 11.000000 12.000000 13.000000 14.000000
[15] 15.000000 16.000000 17.000000 18.000000 19.000000 20.000000
С основанием R:
df <- data.frame(x = sample(c(1:10,NA),1000, replace = T))
window <- 10
lapply(1:(nrow(df)-window), function(x) ifelse(is.na(df[x,'x']),mean(df[x:(x+10),'x'],na.rm=T),df[x,'x']))
Единственная разница у меня в том, что я теперь жду ценностей. Но вы можете изменить это в соответствии со своими спецификациями.
Ваша индексация немного
impute.to.window.mean <- function(x, window) {
na.idx <- which(is.na(x)) #find missing values in x
for (na in na.idx) {
y <- sort(x[(na - window):(na + window)])
x[na] <- mean(y)
}
return(x)
}
Пройдите пример
set.seed(1)
x <- sample(10)
na <- 6
x[na] <- NA
# [1] 3 4 5 7 2 NA 9 6 10 1
window <- 3L
я использовал sort
потому что это опускает NA
S в один шаг; Вы хотите среднее значение этого вектора, которые являются всеми значениями, которые попадают в window
sort(x[(na - window):(na + window)])
# [1] 2 5 6 7 9 10
mean(sort(x[(na - window):(na + window)]))
# [1] 6.5
Проверьте свою функцию сейчас
impute.to.window.mean(x, window)
# [1] 3.0 4.0 5.0 7.0 2.0 6.5 9.0 6.0 10.0 1.0
редактировать
На самом деле, вы, вероятно, должны использовать
y <- sort(x[pmax(1L, (na - window)):pmin(length(x), (na + window))])
вместо этого для случая, когда NA
происходит, скажем, в 2, и ваше окно> 1
## current version
impute.to.window.mean(x, 10)
# Error in x[(na - window):(na + window)] :
# only 0's may be mixed with negative subscripts
## version with pmax/pmin
impute.to.window.mean(x, 10)
# [1] 3.000000 4.000000 5.000000 7.000000 2.000000 5.222222 9.000000 6.000000 10.00000 1.000000
mean(sort(x))
# [1] 5.222222
impute.to.window.mean <- function(x, window) {
na.idx <- which(is.na(x)) #find missing values in x
for (na in na.idx) {
# y <- sort(x[(na - window):(na + window)])
y <- sort(x[pmax(1L, (na - window)):pmin(length(x), (na + window))])
x[na] <- mean(y)
}
return(x)
}
В функции preProcess пакета «Caret» есть метод под названием «knnImpute», который делает именно это. Попробуй.