Проблемы с индексами и операторами ifelse при попытке заменить цикл for - PullRequest
0 голосов
/ 29 июня 2019

Я хотел бы заменить следующий цикл 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. (Обратите внимание, что мой настоящий код обращается к фрейму данных. Поэтому решение должно работать для фреймов данных.)

...