У меня есть вложенный список фреймов данных, и я хочу выполнять действия только с указанным 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)