Заполнение отсутствующих значений по группам в data.table

Если вы хотите заполнить отсутствующие значения переменной, основанные на предыдущем / заднем не-NA-наблюдении внутри группы, команда data.table

setkey(DT,id,date) DT[, value_filled_in := DT[!is.na(value), list(id, date, value)][DT[, list(id, date)], value, roll = TRUE]] 

что довольно сложно. Это позор, так как roll – это очень быстрый и мощный вариант (esp по сравнению с применением такой функции, как zoo::na.locf в каждой группе)

Я могу написать функцию удобства для заполнения пропущенных значений

  fill_na =0) c(FALSE,TRUE) else c(TRUE,FALSE)){ id <- seq_along(x) if (is.null(by)){ DT <- data.table("x" = x, "id" = id, key = "id") return(DT[!is.na(x)][DT[, list(id)], x, roll = roll, rollends = rollends, allow.cartesian = TRUE]) } else{ DT <- data.table("x" = x, "by" = by, "id" = id, key = c("by", "id")) return(DT[!is.na(x)][DT[, list(by, id)], x, roll = roll, rollends = rollends, allow.cartesian = TRUE]) } } 

А потом напишите

 setkey(DT,id, date) DT[, value_filled_in := fill_na(value, by = id)] 

Это не очень приятно, так как хотелось бы написать

 setkey(DT,id, date) DT[, value_filled_in := fill_na(value), by = id] 

Однако для этого требуется огромное количество времени. И для конечного пользователя громоздко узнать, что fill_na следует вызывать с опцией by и не следует использовать с data.table by . Есть ли элегантное решение вокруг этого?

Некоторое испытание скорости

 N <- 2e6 set.seed(1) DT <- data.table( date = sample(10, N, TRUE), id = sample(1e5, N, TRUE), value = sample(c(NA,1:5), N, TRUE), value2 = sample(c(NA,1:5), N, TRUE) ) setkey(DT,id,date) DT user system elapsed #> 0.086 0.006 0.105 system.time(DT[, filled1 := zoo::na.locf.default(value, na.rm = FALSE), by = id]) #> user system elapsed #> 5.235 0.016 5.274 # (lower speed and no built in option like roll=integer or roll=nearest, rollend, etc) system.time(DT[, filled2 := fill_na(value, by = id)]) #> user system elapsed #> 0.194 0.019 0.221 system.time(DT[, filled3 := fill_na(value), by = id]) #> user system elapsed #> 237.256 0.913 238.405 

Почему я просто не использую na.locf.default ? Несмотря на то, что разница в скорости не очень важна, эта же проблема возникает и для других видов команд data.table (которые полагаются на слияние переменной в «by») – это позор систематически игнорировать их, чтобы получить более простой синтаксис. Мне также очень нравятся все варианты рулона.

Вот несколько более быстрый и компактный способ сделать это (версия 1.9.3+):

 DT[, filled4 := DT[!is.na(value)][DT, value, roll = T]] 
  • R раунд до ближайшего .5 или .1
  • Как указать фактические значения оси x для построения в виде x-оси тиков в R
  • Доступ к столбцам в data.table с использованием символьного вектора имен столбцов
  • Сохранять только минимальное значение для каждого уровня фактора
  • Условное слияние / замена в R
  • Определение типов данных столбцов фрейма данных
  • Выполните полусоединение с data.table
  • Быстрое чтение очень больших таблиц в качестве данных
  • Отображение времени в командной строке R
  • Согласованная ширина для geom_bar в случае отсутствия данных
  • ограниченная оптимизация в R
  • Давайте будем гением компьютера.