Я хотел бы заменить следующий цикл for
, потому что должен быть более простой способ, а циклу for
требуются годы для вычисления, если кадр данных становится очень большим.
Пример кадра данных df
состоит из нескольких столбцов. Каждый столбец имеет длину 1000 записей. Столбец ID
содержит буквенно-цифровые идентификаторы, в то время как все остальные столбцы содержат числа NA
s.
ID <- c(rep("ID1", 400), rep("ID2", 400), rep("ID3", 200))
set.seed(264060397)
A <- round((runif(1000, 1.0, 1000.0)), digits = 2)
A[sort(sample(c(1:1000), 50, replace = TRUE))] <- NA
B <- round((runif(1000, 1.0, 1000.0)), digits = 2)
B[sort(sample(c(1:1000), 35, replace = TRUE))] <- NA
C <- round((runif(1000, 1.0, 1000.0)), digits = 2)
C[sort(sample(c(1:1000), 243, replace = TRUE))] <- NA
df <- data.table(ID, A, B, C)
Теперь я хотел бы добавить новый столбец с именем D
, который должен содержать вычисляемые значения. Цикл for
делает то, что он должен делать, но для завершения кадра требуется очень много времени. 1000, однако, не должно быть проблемой для вычисления. С другой стороны, 15 000 могут привести к довольно занятой петле for
.
df[, D := NA]
df$D = as.numeric(as.character(df$D))
df <- as.data.frame(df)
for(i in 2:length(df$ID)) {
if(df$ID[i] == df$ID[i - 1]) {
if(is.na(df$C[i])) {
df$D[i] <-
df$A[i] - df$A[i - 1] -
df$B[i] - df$B[i - 1]
} else {
df$D[i] <-
df$A[i] - df$A[i - 1]
}
}
}
View(df)
показывает, что некоторые значения D
равны NA
с, но это не имеет значения.
Затем я попытался ускорить вычисления, избегая циклов for
. Это, однако, не работает.
df$D <- NULL
i = c(1:length(df$ID))
df[, D := ifelse(i == 1 || !(df$ID[i] == df$ID[i - 1]), NA,
ifelse(is.na(df$C[i]),
df$A[i] - df$A[i - 1] -
df$B[i] - df$B[i - 1],
df$A[i] - df$A[i - 1]
))]
В этом примере R выдает следующее сообщение об ошибке:
Check that is.data.table(DT) == TRUE. Otherwise, := and `:=`(...) are defined for use in j, once only and in particular ways. See help(":=").
Если я не преобразую df
из таблицы данных в фрейм данных, написав df <- as.data.frame(df)
, R не выдаст сообщение об ошибке. Однако столбец D
содержит только NA
с. Это не те результаты, которые рассчитывает цикл for
. (Обратите внимание, что мой настоящий код обращается к фрейму данных. Поэтому решение должно работать для фреймов данных.)