Вмените пропущенные значения со средним значением 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)
}

но это неправильно, и я не знаю, как продолжить.


person s1368647    schedule 06.02.2017    source источник


Ответы (5)


Возможно, вы захотите рассмотреть возможность использования пакета imputeTS. Вот пример заполнения значений простой скользящей средней и окном 4:

x <- rnorm(100)
x[c(7, 21, 33)] <- NA

imputeTS::na.ma(x, k = 4, weighting = "simple")
person Raad    schedule 06.02.2017

Используя 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
person G. Grothendieck    schedule 06.02.2017

с основанием 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']))

Единственная разница у меня в том, что теперь я с нетерпением жду значений. Но вы можете изменить это в соответствии с вашими требованиями.

person Wietze314    schedule 06.02.2017

Ваша индексация немного не работает

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 за один шаг; вам нужно среднее значение этого вектора, которое представляет собой все значения, попадающие в 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)
}
person rawr    schedule 06.02.2017

Функция preProcess пакета Caret имеет метод knnImpute, который делает именно это. Попробуй.

person Faustin Gashakamba    schedule 15.02.2021