Возможно, разделение должно выполняться с помощью оператора data.table
by=
, возможно, более эффективно.
Поскольку у меня не установлено imputeTS
(есть несколько вложенных зависимостей, которых у меня нет ), Я подделаю вменение, используя zoo::na.locf
, оба вперед / назад. Я не предлагаю, чтобы это был ваш механизм вменения, я использую его для демонстрации более распространенного паттерна с data.table
.
myimpute <- function(z) zoo::na.locf(zoo::na.locf(z, na.rm = FALSE), fromLast = TRUE, na.rm = FALSE)
Теперь некоторые эквивалентные вызовы, один с вашим with(dt, ...)
и моим альтернативы (которые на самом деле являются пошаговыми инструкциями до моего окончательного предложения 5
):
dt[, MPR_kalman1 := with(dt, ave(MPR, State, CC, ID, FUN = myimpute))]
dt[, MPR_kalman2 := with(.SD, ave(MPR, State, CC, ID, FUN = myimpute))]
dt[, MPR_kalman3 := with(.SD, ave(MPR, FUN = myimpute)), by = .(State, CC, ID)]
dt[, MPR_kalman4 := ave(MPR, FUN = myimpute), by = .(State, CC, ID)]
dt[, MPR_kalman5 := myimpute(MPR), by = .(State, CC, ID)]
# Year State CC ID MPR MPR_kalman1 MPR_kalman2 MPR_kalman3 MPR_kalman4 MPR_kalman5
# 1: 2002 15 3 3 NA 193 193 193 193 193
# 2: 2003 15 3 3 NA 193 193 193 193 193
# 3: 2004 15 3 3 193 193 193 193 193 193
# 4: 2005 15 3 3 193 193 193 193 193 193
# 5: 2006 15 3 3 348 348 348 348 348 348
# 6: 2007 15 3 3 388 388 388 388 388 388
# 7: 2008 15 3 3 388 388 388 388 388 388
# 8: 1999 53 33 1 NA 170 170 170 170 170
# 9: 2000 53 33 1 NA 170 170 170 170 170
# 10: 2002 53 33 1 NA 170 170 170 170 170
# 11: 2003 53 33 1 NA 170 170 170 170 170
# 12: 2004 53 33 1 NA 170 170 170 170 170
# 13: 2005 53 33 1 170 170 170 170 170 170
# 14: 2006 53 33 1 170 170 170 170 170 170
# 15: 2007 53 33 1 330 330 330 330 330 330
# 16: 2008 53 33 1 330 330 330 330 330 330
Два метода дают одинаковые результаты, но последний сохраняет многие из показателей эффективности памяти, которые могут сделать data.table
предпочтительнее.
Использование with(dt, ...)
является анти-паттерном в одном случае и серьезным риском в другом. Что касается «риска», поймите, что data.table
может многое сделать за кулисами, так что вычисления / вызовы функций в компоненте j=
(второй аргумент) видят только данные, которые имеют отношение к делу. Ярким примером является группировка, но другим (не связанным с этим) примером data.table
является условная замена, как в dt[is.na(x), x := -1]
. Со ссылкой на входную таблицу dt
внутри этого, если когда-либо будет что-то в первом аргументе (условная замена) или by=
аргументе, то это терпит неудачу.
MPR_kalman2
уменьшает это с помощью .SD
, который является data.table
способом замены данных, которые будут использоваться, на "S
ubset D
ata " ( ref ). Но он по-прежнему не использует существенную эффективность data.table
в работе с группами в оперативной памяти.
MPR_kalman3
работает над этим, группируя снаружи, все еще используя with
, но не (как в * 1042). *) более дружественным образом.
MPR_kalman4
исключает использование with
, поскольку действительно MPR
, видимый для ave
, все равно есть только в каждой группе. И потом, когда вы думаете об этом, так как ave
не дана группирующая переменная, она просто передает все данные MPR
напрямую в myimpute
. Исходя из этого, у нас есть MPR_kalman5
, прямой метод, который работает по обычным схемам data.table
.
Хотя я не знаю , что это уменьшит ваш сбой, это намеревался очень эффективно использовать память (data.table
).