Разделить набор данных на основе столбца с циклом

#r #loops #data.table

#r #циклы #data.table

Вопрос:

Я пытался получить цикл, который разбивает набор данных на несколько наборов данных на основе значения столбца. Однако набор данных имеет формат, который я раньше не обрабатывал (т. Е. Список, содержащий как списки, так и data.tables). Набор данных воспроизводится с помощью:

 table1 <- data.table::data.table(Scenario = 
                            c(rep(
                              c("A", "B", "C", "D"), 
                              4)),
                          A = c(
                            rep("x", 4), rep("b", 4), rep("s", 4),
                            rep("u", 4)),
                          Correlation = c(1, 0.125, 0.1, 0, 
                                          0.125, 1, 0.2, 0, 
                                          0.1, 0.2,   1, 0, 
                                          0,     0,   0, 1),
                          Matrix = "IM",
                          stringsAsFactors = FALSE,
                          check.names = FALSE)
table2 <- data.table::data.table(Scenario = 
                         c(rep(
                           c("A", "B", "C", "D"), 
                           4)),
                       A = c(
                         rep("x", 4), rep("b", 4), rep("s", 4),
                         rep("u", 4)),
                       Correlation = c(1, 0.125, 0.1, 0, 
                                       0.125, 1, 0.2, 0, 
                                       0.1, 0.2,   1, 0, 
                                       0,     0,   0, 1),
                       Matrix = "IM",
                       stringsAsFactors = FALSE,
                       check.names = FALSE)

table3 <- data.table::data.table(Scenario = 
                         c(rep(
                           c("A", "B", "C", "D"), 
                           4)),
                       A = c(
                         rep("x", 4), rep("b", 4), rep("s", 4),
                         rep("u", 4)),
                       Correlation = c(1, 0.125, 0.1, 0, 
                                       0.125, 1, 0.2, 0, 
                                       0.1, 0.2,   1, 0, 
                                       0,     0,   0, 1),
                       Matrix = "IM",
                       stringsAsFactors = FALSE,
                       check.names = FALSE)

list1 <- list("a" = "2019", "b" = "2020", "c" = "2021")
list2 <- list("a" = "test", "b" = "test", "c" = "test")

input_data <- list("table1" = table1, "table2" = table2, "table3" = table3, 
"list1"=list1, "list2" = list2)
 

Мне нужен цикл, который разделяет этот набор данных на основе всех уникальных экземпляров в столбце сценария. Первый набор данных (для значения сценария «A») воспроизводится с помощью:

 table1 <- data.table::data.table(Scenario = 
                               c(rep(
                                 c("A"), 
                                 4)),
                             A = c(
                               rep("x", 1), rep("b", 1), rep("s", 1),
                               rep("u", 1)),
                             Correlation = c(1, 0.125, 0.1, 0 ),
                             Matrix = "IM",
                             stringsAsFactors = FALSE,
                             check.names = FALSE)
table2 <- data.table::data.table(Scenario = 
                               c(rep(
                                 c( "A"), 
                                 4)),
                             A = c(
                               rep("x", 1), rep("b", 1), rep("s", 1),
                               rep("u", 1)),
                             Correlation = c(1, 0.125, 0.1, 0),
                             Matrix = "IM",
                             stringsAsFactors = FALSE,
                             check.names = FALSE)

table3 <- data.table::data.table(Scenario = 
                               c(rep(
                                 c("A"), 
                                 4)),
                             A = c(
                               rep("x", 1), rep("b", 1), rep("s", 1),
                               rep("u", 1)),
                             Correlation = c(1, 0.125, 0.1, 0),
                             Matrix = "IM",
                             stringsAsFactors = FALSE,
                             check.names = FALSE)

list1 <- list("a" = "2019", "b" = "2020", "c" = "2021")
list2 <- list("a" = "test", "b" = "test", "c" = "test")

input_data <- list("table1" = table1, "table2" = table2, "table3" = table3, 
               "list1"=list1, "list2" = list2)
 

Пожалуйста, дайте мне знать, если потребуется дополнительная информация.

Ответ №1:

Вы можете написать функцию, которая переносит lapply , используя inherits в качестве проверки тип каждого объекта в списке. Если объект наследует data.frame и содержит столбец с именем Scenario , вы можете просто подмножество его. Элементы, которые не являются фреймами данных или таблицами данных, или те, у которых нет вызываемых столбцов Scenario , остаются неизменными:

 get_scenario <- function(S) {
  lapply(input_data, function(x) {
    if(!inherits(x, "data.frame")) 
      return(x) 
    else if(!"Scenario" %in% names(x))
      return(x)
    
    return(x[x$Scenario == S,])
    })
}
 

Это позволяет:

 get_scenario("A")
#> $table1
#>    Scenario A Correlation Matrix
#> 1:        A x       1.000     IM
#> 2:        A b       0.125     IM
#> 3:        A s       0.100     IM
#> 4:        A u       0.000     IM
#> 
#> $table2
#>    Scenario A Correlation Matrix
#> 1:        A x       1.000     IM
#> 2:        A b       0.125     IM
#> 3:        A s       0.100     IM
#> 4:        A u       0.000     IM
#> 
#> $table3
#>    Scenario A Correlation Matrix
#> 1:        A x       1.000     IM
#> 2:        A b       0.125     IM
#> 3:        A s       0.100     IM
#> 4:        A u       0.000     IM
#> 
#> $list1
#> $list1$a
#> [1] "2019"
#> 
#> $list1$b
#> [1] "2020"
#> 
#> $list1$c
#> [1] "2021"
#> 
#> 
#> $list2
#> $list2$a
#> [1] "test"
#> 
#> $list2$b
#> [1] "test"
#> 
#> $list2$c
#> [1] "test"
 

И если вы хотите, чтобы все подгруппы были одним uber-списком, вы можете сделать:

 lapply(c("A", "B", "C"), get_scenario)