【问题标题】:R - Extracting information from list of lists of data.framesR - 从 data.frames 列表中提取信息
【发布时间】:2017-06-10 21:26:53
【问题描述】:

我有两个需求,都连接到类似于下面可重现的数据集。我有一个包含 18 个实体的列表,每个实体都由 17-19 个 data.frames 的列表组成。以下是可重现的数据集(有矩阵而不是 data.frames,但我认为这不会产生影响):

test <- list(list(matrix(10:(50-1), ncol = 10), matrix(60:(100-1), ncol = 10), matrix(110:(150-1), ncol = 10)),
             list(matrix(200:(500-1), ncol = 10), matrix(600:(1000-1), ncol = 10), matrix(1100:(1500-1), ncol = 10)))
  1. 我需要将每个数据帧/矩阵分成两部分(按给定的行数)并保存到新的列表列表中
  2. 其次,我需要从列表列表中的每个 data.frame 中提取并保存给定的列。

除了for(),我不知道如何去做,但我相信apply() 系列函数应该是可能的。

感谢您的阅读

编辑:

我的预期输出如下所示:

extractedColumns <- list(list(matrix(10:(50-1), ncol = 10)[, 2], matrix(60:(100-1), ncol = 10)[, 2], matrix(110:(150-1), ncol = 10)[, 2]),
                         list(matrix(200:(500-1), ncol = 10)[, 2], matrix(600:(1000-1), ncol = 10)[, 2], matrix(1100:(1500-1), ncol = 10)[, 2]))


numToSubset <- 3
substetFrames <- list(list(list(matrix(10:(50-1), ncol = 10)["first length - numToSubset rows", ], matrix(10:(50-1), ncol = 10)["last numToSubset rows", ]), 
                           list(matrix(60:(100-1), ncol = 10)["first length - numToSubset rows", ], matrix(60:(100-1), ncol = 10)["last numToSubset rows", ]),
                                list(matrix(110:(150-1), ncol = 10)["first length - numToSubset rows", ], matrix(110:(150-1), ncol = 10)["last numToSubset rows", ])),
                      etc...)

它看起来很乱,希望你能按照我想要的。

【问题讨论】:

  • lapply() 的用法看起来很简单,可能是嵌套的。你能用你想要的输出更新帖子吗?
  • 谢谢。编辑了我的问题
  • 所需的输出不是清晰的,也不是完全可运行的代码,而是伪代码。 extractedColumns 或 substetFrames 是哪一个?在 #2 中,您说提取给定列,但您尝试为substetFrames 提取行,即使在伪代码中使用 rows 一词?
  • @Parfait:感谢您的回复。实际上我认为这很清楚,请让我知道您认为不清楚的地方。我想要两个输出(2 个问题)-subsetFrames 是给定行的 2 个帧子集的列表,extractColumn 是从原始数据帧中提取的列的列表。它对应于我的两个问题(尽管顺序相反,如果这让你感到困惑)

标签: r list dataframe subset


【解决方案1】:

你可以使用两个嵌套的lapplys:

lapply(test, function(x) lapply(x, '[', c(2, 3)))

输出:

[[1]]
[[1]][[1]]
[1] 11 12

[[1]][[2]]
[1] 61 62

[[1]][[3]]
[1] 111 112


[[2]]
[[2]][[1]]
[1] 201 202

[[2]][[2]]
[1] 601 602

[[2]][[3]]
[1] 1101 1102

说明

第一个lapply 将应用于test 的两个列表。这两个列表中的每一个都包含另一个 3。第二个 lapply 将遍历这 3 个列表和子集(即第二个 lapply 中的 '[' 函数)列 c(2, 3)。

注意:在矩阵[ 的情况下,将子集元素 2 和 3,但在 data.frame 上使用时,相同的函数将对列进行子集。

子集行和列

lapply 使用匿名函数非常灵活。通过将代码更改为:

#change rows and columns into what you need
lapply(test, function(x) lapply(x, function(y) y[rows, columns]))

您可以指定所需的行或列的任意组合。

【讨论】:

  • 我的第二个问题的完美解决方案 - 提取数据帧的给定列。也真的很欣赏解释。我还有一个问题 - 如何按行减去数据帧(例如,每个数据帧按行分成两半并保存到数据帧列表的新列表中)?如果您也可以回答,我将不胜感激并接受您的回答。
  • 试过这个。当我在给定的数据帧上使用split() 时它可以工作,但是当与“x”一起使用时,它会引发以下错误:splitFrames &lt;- lapply(test, function(x) split(x, c(rep(1, dim(x)[1] - 3), rep(2, 3)))) Error in rep(1, dim(x)[1] - 3) : invalid 'times' argument
  • 我已经更新了答案。解释和我之前写的完全一样。用例如替换行1:5 和带有 c(2,3) 的列将为每个 data.frames 提取前 5 行和 2,3 列。
  • split 不是正确的方法。嵌套lapplys 是正确的方式。
  • 不客气。 R 社区正在成长,人们愿意帮助他人,这总是很好:)。如果您的实际数据不是太复杂(因为 data.frames 具有相同的结构),我会避免使用 split,因为它会创建更多列表。带有嵌套lapplys 的简单子集应该可以正常工作。这需要一些练习,但你会做到的!
【解决方案2】:

要搭载@LyzanderR 的答案,请考虑应用系列中经常被忽略的兄弟rapply,它可以在向量/矩阵列表上递归运行函数,返回此类嵌套结构。通常它可以与嵌套的lapply 或其变体v/sapply 进行比较:

newtest1 <- lapply(test, function(x) lapply(x, '[', c(2, 3)))

newtest2 <- rapply(test, function(x) `[`(x, c(2, 3)), classes="matrix", how="list")

all.equal(newtest1, newtest2)
# [1] TRUE

有趣的是,令我惊讶的是,rapply 在这个用例中的运行速度比嵌套的lapply 慢!嗯嗯,回实验室我去……

library(microbenchmark)

microbenchmark(newtest1 <- lapply(test, function(x) lapply(x, '[', c(2, 3))))    
# Unit: microseconds
#     mean median     uq    max neval
# 31.92804 31.278 32.241 74.587   100

microbenchmark(newtest2 <- rapply(test, function(x) `[`(x, c(2, 3)),
                                        classes="matrix", how="list"))    
# Unit: microseconds
#    min    lq     mean median      uq    max neval
# 69.293 72.18 79.53353 73.143 74.5865 219.91   100

更有趣的是,为等效矩阵括号移除 [ 运算符,嵌套的 lapply 运行得更好,rapply 更糟!

microbenchmark(newtest3 <- lapply(test, function(x) 
                                  lapply(x, function(y) y[c(2, 3), 1])))
# Unit: microseconds
#    min     lq     mean median     uq    max neval
# 26.947 28.391 32.00987 29.354 30.798 100.09   100

all.equal(newtest1, newtest3)
# [1] TRUE

microbenchmark(newtest4 <- rapply(test, function(x) x[c(2,3), 1], 
                                  classes="matrix", how="list"))
# Unit: microseconds
#    min     lq     mean median     uq     max neval
# 74.105 76.752 80.37076 77.955 78.918 203.549   100

all.equal(newtest2, newtest4)
# [1] TRUE

【讨论】:

    猜你喜欢
    • 2020-02-13
    • 1970-01-01
    • 2017-12-12
    • 2019-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多