lapply data.table setDT во вложенных списках не работает или не идемпотентен? - PullRequest
1 голос
/ 16 января 2020

У меня есть вложенный список фреймов данных, и я хочу выполнять действия только с указанным c элементом фрейма данных с именем "train_set"

library(data.table)

train_set <- data.frame(
  x = c(rep(2, 10)), 
  y = c(0:9), 
  z = c(rep("Factor1", 10)))

test_set <- data.frame(
  x = c(rep(1, 12)), 
  y = c(0:11), 
  z = c(rep("Factor2", 12)))

row.names(train_set) <- c(paste("Observation", c(1:nrow(train_set)), sep = "_"))
row.names(test_set) <- c(paste("Observation", c(1:nrow(test_set)), sep = "_"))

top_list <- list(
  aa = list(train_set = train_set, test_set = test_set), 
  bb = list(train_set = train_set, test_set = test_set), 
  cc = list(train_set = train_set, test_set = test_set)
)

цель состоит в том, чтобы реплицировать строки в train_set, добавьте немного шума и назовите их соответственно. Наконец, я хочу вернуть список, который имеет ту же структуру, что и входной список, но содержит измененные таблицы train_set вместо исходных. Поскольку мой код dplyr для этих действий был довольно медленным, я получил помощь по увеличению производительности с помощью data.table Ускорение конвейера dplyr, включая проверки с mutate_if и if_else для больших таблиц

Однако, чтобы использовать data.table, я должен преобразовать эти специфицированные c data.frames в data.tables. Важно то, что я сохраняю row.names как столбец «Sample», так как мне нужны имена.

# does not work on all elements, not run
# top_list <- lapply(top_list, function(next_level) lapply(next_level, setDT, keep.rownames = "Sample"))

Я пытался использовать вложенные циклы lapply и for, чтобы изменить train_set, весь список или train и test_set на DT, так как в ответе выше упоминалось, что список необходимо обновить. Но я не могу заставить его работать на этот вложенный список. Код, кажется, работает для первой итерации, но не после. Кто-нибудь знает, как я могу превратить все эти DF в DT и запустить приведенный ниже код?

result_list <- list()
counter <- 0
for (split_table in top_list) {
  counter <- counter +1
  current_name <- names(top_list)[counter]
  train_tmp <- split_table$train_set
  test_tmp <- split_table$test_set
  print(current_name)
  print(train_tmp)

  # either here or earlier turn DF into DT, but keep row.names
  setDT(train_tmp, keep.rownames = "Sample")
  print(train_tmp)  # get's ignored in the first iteration?
  # The row names are still present for the first iteration with item "aa"
  cols <- names(train_tmp)[sapply(train_tmp, is.numeric)]
  # this is the function to copy each row two times, add 10 % noise to each numeric column 
  # and append the Sample name with the copy number
  noised_copies <- lapply(c(1,2), function(n) {
    copy(train_tmp)[,
      # here we get the error as we need the column "Sample" to adjust the names of the replicated rows
      c("Sample", cols) := c(.(paste(Sample, n, sep=".")), 
        .SD * sample(c(-1.01, 1.01), .N*ncol(.SD), TRUE)),
      .SDcols=cols]
  })
  # combine original table and table with replicates
  train_noised <- rbindlist(c(noised_copies, list(train_tmp)), use.names = FALSE)
  # turn back into DF and add to result list
  setDF(train_noised, rownames = train_noised$Sample)
  train_noised$Sample <- NULL
  result_list[[current_name]] <- list(train_set = train_noised, test_set = test_tmp)
}
result_list
# it is important to have a clean workspace after each try
rm(top_list)

1 Ответ

1 голос
/ 16 января 2020

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

Я нашел простой двойной l oop работ. Вероятно, он делает копии фреймов данных перед их перезаписью, поэтому я не знаю, будет ли это достаточно быстро для ваших нужд. Кажется, на ваших данных с моей машины уходит около 6 миллисекунд.

for(i in 1:3) 
  for(j in 1:2) 
    top_list[[i]][[j]] <- as.data.table(top_list[[i]][[j]], keep.rownames = "Sample")

Это дает

top_list
#> $`aa`
#> $`aa`$`train_set`
#>             Sample x y       z
#>  1:  Observation_1 2 0 Factor1
#>  2:  Observation_2 2 1 Factor1
#>  3:  Observation_3 2 2 Factor1
#>  4:  Observation_4 2 3 Factor1
#>  5:  Observation_5 2 4 Factor1
#>  6:  Observation_6 2 5 Factor1
#>  7:  Observation_7 2 6 Factor1
#>  8:  Observation_8 2 7 Factor1
#>  9:  Observation_9 2 8 Factor1
#> 10: Observation_10 2 9 Factor1
#> 
#> $`aa`$test_set
#>             Sample x  y       z
#>  1:  Observation_1 1  0 Factor2
#>  2:  Observation_2 1  1 Factor2
#>  3:  Observation_3 1  2 Factor2
#>  4:  Observation_4 1  3 Factor2
#>  5:  Observation_5 1  4 Factor2
#>  6:  Observation_6 1  5 Factor2
#>  7:  Observation_7 1  6 Factor2
#>  8:  Observation_8 1  7 Factor2
#>  9:  Observation_9 1  8 Factor2
#> 10: Observation_10 1  9 Factor2
#> 11: Observation_11 1 10 Factor2
#> 12: Observation_12 1 11 Factor2
#> 
#> 
#> $bb
#> $bb$`train_set`
#>             Sample x y       z
#>  1:  Observation_1 2 0 Factor1
#>  2:  Observation_2 2 1 Factor1
#>  3:  Observation_3 2 2 Factor1
#>  4:  Observation_4 2 3 Factor1
#>  5:  Observation_5 2 4 Factor1
#>  6:  Observation_6 2 5 Factor1
#>  7:  Observation_7 2 6 Factor1
#>  8:  Observation_8 2 7 Factor1
#>  9:  Observation_9 2 8 Factor1
#> 10: Observation_10 2 9 Factor1
#> 
#> $bb$test_set
#>             Sample x  y       z
#>  1:  Observation_1 1  0 Factor2
#>  2:  Observation_2 1  1 Factor2
#>  3:  Observation_3 1  2 Factor2
#>  4:  Observation_4 1  3 Factor2
#>  5:  Observation_5 1  4 Factor2
#>  6:  Observation_6 1  5 Factor2
#>  7:  Observation_7 1  6 Factor2
#>  8:  Observation_8 1  7 Factor2
#>  9:  Observation_9 1  8 Factor2
#> 10: Observation_10 1  9 Factor2
#> 11: Observation_11 1 10 Factor2
#> 12: Observation_12 1 11 Factor2
#> 
#> 
#> $cc
#> $cc$`train_set`
#>             Sample x y       z
#>  1:  Observation_1 2 0 Factor1
#>  2:  Observation_2 2 1 Factor1
#>  3:  Observation_3 2 2 Factor1
#>  4:  Observation_4 2 3 Factor1
#>  5:  Observation_5 2 4 Factor1
#>  6:  Observation_6 2 5 Factor1
#>  7:  Observation_7 2 6 Factor1
#>  8:  Observation_8 2 7 Factor1
#>  9:  Observation_9 2 8 Factor1
#> 10: Observation_10 2 9 Factor1
#> 
#> $cc$test_set
#>             Sample x  y       z
#>  1:  Observation_1 1  0 Factor2
#>  2:  Observation_2 1  1 Factor2
#>  3:  Observation_3 1  2 Factor2
#>  4:  Observation_4 1  3 Factor2
#>  5:  Observation_5 1  4 Factor2
#>  6:  Observation_6 1  5 Factor2
#>  7:  Observation_7 1  6 Factor2
#>  8:  Observation_8 1  7 Factor2
#>  9:  Observation_9 1  8 Factor2
#> 10: Observation_10 1  9 Factor2
#> 11: Observation_11 1 10 Factor2
#> 12: Observation_12 1 11 Factor2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...