Создать столбец TRUE / FALSE в списке фреймов данных на основе значений определенных строк - PullRequest
0 голосов
/ 07 ноября 2018

У меня есть список фреймов данных, содержащих значения из разных «нулевых» и «альтернативных» статистических моделей. Я хотел бы создать новый столбец в каждом кадре данных, который содержит значение TRUE или FALSE для каждой строки. Все «нулевые» модели должны быть назначены как ЛОЖЬ. Все «альтернативные» модели должны быть ЛОЖНЫМИ, если их значение меньше двойного значения для нулевой модели с наибольшим значением. Но любые альтернативные модели, по крайней мере, вдвое превышающие максимальное значение нулевой модели, должны быть ИСТИНА.

Так, например, если у меня есть две альтернативные модели со значениями 3 и 4 и две нулевые модели со значениями 1 и 2, то я хотел бы получить значения FALSE для одной альтернативной модели (значение = 3) и 2 пустых моделей. Но одна альтернативная модель (значение = 4) должна быть ИСТИНА, потому что это в два раза больше нулевого значения модели (значение = 2). Я воспроизвел это в примере «Тест» ниже.

Я могу добиться этого для отдельного фрейма данных (пример «Тест»), но я не знаю, как обойти это через список фреймов данных. Некоторый воспроизводимый код:

####Data import
M1 <- data.frame(matrix(1:4, nrow = 4, ncol = 1))
M2 <- data.frame(matrix(8:11, nrow = 4, ncol = 1))
M3 <- data.frame(matrix(0:3, nrow = 4, ncol = 1))
mlist <- list(M1, M2, M3)
mlist <- lapply(mlist, transform, Logical= NA)##CREATE NEW COLUMN FOR EACH DF

###Define models
row_names <- c("NULL1","NULL2","ALT1","ALT2") 
mlist <- lapply(mlist, "rownames<-", row_names)

Я не уверен, что делать отсюда. Вот процедура, которую я хотел бы принять для одного кадра данных.

###Perform for one DF individually
Test <- mlist[[1]]
null_models<-which(rownames(Test)=="NULL1" | rownames(Test)== "NULL2")

for (i in 1:nrow(Test)){
  if (all(Test[null_models,1]<=(Test[i,1]/2))) {
   Test$Logical[i]<-"TRUE"
} else {
Test$Logical[i]<-"FALSE"
}}
Test

Но я не знаю, как применить этот код к списку фреймов данных. Заранее благодарю за любую помощь в этом.

1 Ответ

0 голосов
/ 07 ноября 2018

Вы почти у цели. Оберните ваш код в функцию, которая принимает один аргумент (элемент списка).

customFunction <- function(x) {
  Test <- x
  null_models <- which(rownames(Test) == "NULL1" | rownames(Test) == "NULL2")

  for (i in 1:nrow(Test)){
    if (all(Test[null_models, 1]<=(Test[i,1]/2))) {
      Test$Logical[i]<-"TRUE"
    } else {
      Test$Logical[i]<-"FALSE"
    }}
  Test
}

> lapply(mlist, FUN = customFunction)
[[1]]
      matrix.1.4..nrow...4..ncol...1. Logical
NULL1                               1   FALSE
NULL2                               2   FALSE
ALT1                                3   FALSE
ALT2                                4    TRUE

[[2]]
      matrix.8.11..nrow...4..ncol...1. Logical
NULL1                                8   FALSE
NULL2                                9   FALSE
ALT1                                10   FALSE
ALT2                                11   FALSE

[[3]]
      matrix.0.3..nrow...4..ncol...1. Logical
NULL1                               0   FALSE
NULL2                               1   FALSE
ALT1                                2    TRUE
ALT2                                3    TRUE

Вот краткий вариант внутреннего цикла:

for (i in 1:nrow(Test)) Test$Logical[i] <- all(Test[null_models,1]<=(Test[i,1]/2))

Также возможна замена цикла на apply() -звук (то есть скрытие цикла):

T0 <- Test[null_models,1]
Test$Logical <- apply(T0 <= matrix(Test[,1]/2, length(null_models), nrow(Test), byrow = TRUE), 2, all)

или

Test$Logical <- apply(sapply(Test[null_models,1], '<=', Test[,1]/2), 1, all)
...