【问题标题】:Split list based on rows of list items根据列表项的行拆分列表
【发布时间】:2020-04-22 06:43:20
【问题描述】:

我正在尝试将我的数据框列表拆分为某种子组,例如嵌套列表或多个列表。拆分应该基于每个数据帧的行数,因此具有相同行数的数据帧应该在同一个列表中结束。

full_list <- list(
  df1 = replicate(10, sample(0:1, 10, replace = TRUE)),
  df2 = replicate(10, sample(0:1, 15, replace = TRUE)),
  df3 = replicate(10, sample(0:1, 20, replace = TRUE)),
  df4 = replicate(10, sample(0:1, 10, replace = TRUE))
)

现在有两个带有nrow() == 10 的数据框,所以它们应该在自己的列表或子列表中结束

我尝试过这样的事情,但我认为split 不适用于列表:

sublist <- lapply(full_list, function(x) split(full_list, f = nrow(x)))

顺便说一句:更大的目标是将所有数据帧拆分为训练数据集和测试数据集,用于使用以下函数进行机器学习。 sample 将用于创建子集,但我希望相同长度的数据帧使用相同的 sample_vector。因此,我想事先将完整列表拆分为子列表。之后,我将再次将所有数据帧放在一起以进行进一步处理(拆分-应用-组合)。只是提一下我是否可能在这里使事情过于复杂。

# function to split data frames in each sub list into train and test data frames 
counter <- 0
train_test_list <- list()
for (x_table in sublist) {
  counter <- counter + 1
  current_name <- paste(names(sublist)[counter], sep = "_")

  sample_vector <- sample.int(n = nrow(x_table), 
    size = floor(0.8 * nrow(x_table)), replace = FALSE)
  train_set <- x_table[sample_vector, ]
  test_set  <- x_table[-sample_vector, ]

  train_test_list[[current_name]] <- list(
    train_set = train_set, test_set = test_set, 
    table_name = names(sublist)[counter]
  )
}
# combine all lists with test and train pairs back into one list 
full_train_test_list <- c(train_test_list1, train_test_list2, train_test_list3, ...)

【问题讨论】:

    标签: r list split


    【解决方案1】:

    我们可以根据该信息获得sapplysplit 的行数

    new_list <- split(full_list, sapply(full_list, nrow))
    str(new_list)
    #List of 3
    # $ 10:List of 2
    #  ..$ df1: int [1:10, 1:10] 1 0 0 1 1 0 1 0 0 1 ...
    #  ..$ df4: int [1:10, 1:10] 1 0 1 1 1 0 0 0 1 1 ...
    # $ 15:List of 1
    #  ..$ df2: int [1:15, 1:10] 0 1 1 0 0 0 0 0 0 1 ...
    # $ 20:List of 1
    #  ..$ df3: int [1:20, 1:10] 1 1 0 1 0 1 1 1 0 1 ...
    

    由于它是一个嵌套的list,我们可以通过在第一个lapply内部调用lapply来在内部list中进行处理

    traintestlst <- lapply(new_list, function(sublst) lapply(sublst, function(x_table) {
    
         sample_vector <- sample.int(n = nrow(x_table), 
                    size = floor(0.8 * nrow(x_table)), replace = FALSE)
          train_set <- x_table[sample_vector, ]
          test_set  <- x_table[-sample_vector, ]
          list(train_set = train_set, test_set = test_set)
    
    
         })
        )
    

    -检查输出

    traintestlst[[1]]$df1
    #$train_set
    #     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
    #[1,]    1    1    0    1    0    0    1    1    1     0
    #[2,]    1    0    1    1    1    0    0    0    1     0
    #[3,]    0    1    0    0    1    1    0    1    1     0
    #[4,]    1    1    0    1    0    0    1    0    0     1
    #[5,]    0    0    0    1    0    0    1    0    1     0
    #[6,]    0    1    1    0    1    0    1    0    1     0
    #[7,]    1    0    1    1    0    0    0    0    0     1
    #[8,]    0    1    0    0    0    1    0    0    1     0
    
    #$test_set
    #     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
    #[1,]    0    0    0    0    0    1    0    1    0     1
    #[2,]    1    0    0    0    0    0    0    1    1     0
    

    【讨论】:

    • 看起来很棒!您是否有建议如何应用于每个子集,例如如何在 for 循环中处理它们?编辑:我刚看到unlistrecursive = FALSE,我会试试的
    • @crazysantaclaus 现在,我们有一个 listlist。您可以使用嵌套的lapply,即lapply(new_list, function(sublist) lapply(sublist, yourfn))
    • 嘿,谢谢你的额外回答,这对我来说是完美的!
    • 还有一件事,我正在尝试将生成sample_vector 的行向上移动一级。 ATM 为每个x_table 创建一个新向量,但它应该只为每个sublst 更改
    • 这正是我想要发布的,太棒了!
    猜你喜欢
    • 1970-01-01
    • 2011-01-05
    • 2018-10-24
    • 2013-02-27
    • 2010-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多