R - 从数据框的列表列表中提取信息

4

我有两个需求,都与下面可重现的数据集类似。我有一个包含18个实体的列表,每个实体由17-19个数据框组成。可重现的数据集如下所示(其中有矩阵而不是数据框,但我不认为这会有什么影响):

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...)

它看起来非常混乱,希望您能理解我想表达的意思。


2
这看起来是使用lapply()的相当简单的方式,可能需要嵌套。您能否更新帖子并提供所需的输出? - C8H10N4O2
非常感谢您编辑了我的问题。 - pun11
所需的输出不明确,也不是完全可运行的代码,而是伪代码。是extractedColumns还是substetFrames呢?在第2点中,你说提取给定的列,但是你尝试使用伪代码中的单词rows进行substetFrames的提取,这是正确的吗? - Parfait
@Parfait:感谢您的回复。实际上,我认为这很清楚,请告诉我您觉得不清楚的地方。我想要两个输出(2个问题)- subsetFrames是由给定行子集的2个框架列表,extractColumn是从原始数据框中提取的列列表。它对应于我的两个问题(尽管顺序相反,如果这让您感到困惑)。 - pun11
2个回答

6
你可以使用两个嵌套的lapply函数:
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的两个列表。这两个列表中每个都包含另外三个列表。第二个lapply将迭代遍历这3个列表并对列c(2, 3)进行子集化(即第二个lapply中的'['函数)。

注意:在矩阵的情况下,[将子集元素2和3,但同样的函数在数据框上使用时将子集列。

子集化行和列

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

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

您可以指定任何想要的行或列的组合。


尝试过这个方法。当我在给定的数据框上使用split()时,它可以正常工作,但是当在lapply中与"x"一起使用时,会抛出以下错误:`splitFrames <- 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` - pun11
好的,我想我明白了。但这都是因为你的帮助 - 我从未尝试过使用嵌套应用程序。请继续保持,我们从像你这样的人身上学到很多!splitFrames <- lapply(test, function(x) lapply(x, function(y) split(y, c(rep(1, dim(y)[1] - 3), rep(2, 3))))) - pun11
在我发布前没注意到这个更新。很高兴知道另一个解决方案。 - pun11
1
非常欢迎您。R社区正在壮大,人们乐于帮助他人,这总是很好的 :). 如果您的实际数据不太复杂(例如data.frames具有相同的结构),我建议避免使用split,因为它会创建更多的列表。简单的子集取值和嵌套的lapply应该可以很好地解决问题。需要一些练习,但您会成功的! - LyzandeR
在 R 中,所有内容都是函数,包括 ['['(1:5, 1)1:5[1] 是相同的。你可以使用 lapply(x, '[', 1:5, c(2, 3))1:5c(2,3) 是传递给 [ 的参数。有许多关于如何使用 lapply 的教程,你可以从中受益。只需谷歌搜索如何使用 lapply 即可。 - LyzandeR
显示剩余4条评论

1
考虑到 @LyzandeR 的回答,可以看看 apply 函数族中经常被忽视的兄弟函数 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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接