2015-10-06 95 views
3

我想重新组织我的数据,基本上是一个data.frames列表。 其元素代表感兴趣的主题(A和B),在两次(1和2)中收集对x和y的观察。 我想使这个列表包含涉及主题的data.frames,其中收集x和y的信息将作为新变量存储在相应的data.frames中,而不是元素名称:在R中,根据元素名称(rbind和指示符变量)重组列表

library('rlist') 

A1 <- data.frame(x=sample(1:100,2),y=sample(1:100,2)) 
A2 <- data.frame(x=sample(1:100,2),y=sample(1:100,2)) 
B1 <- data.frame(x=sample(1:100,2),y=sample(1:100,2)) 
B2 <- data.frame(x=sample(1:100,2),y=sample(1:100,2)) 

list <- list(A1=A1,A2=A2,B1=B1,B2=B2) 

A <- do.call(rbind,list.match(list,"A")) 
B <- do.call(rbind,list.match(list,"B")) 

list <- list(A=A,B=B) 
list <- lapply(list,function(x) { 
     y <- data.frame(x) 
     y$class <- c(rep.int(1,2),rep.int(2,2)) 
     return(y) 
}) 

> list 
$A 
     x y class 
A1.1 66 96  1 
A1.2 76 58  1 
A2.1 50 93  2 
A2.2 57 12  2 

$B 
     x y class 
B1.1 58 56  1 
B1.2 69 15  1 
B2.1 77 77  2 
B2.2 9 9  2 

在我的现实世界的问题中,有大约500个科目,并不总是两次,不同数量的观察。

所以我上面的示例只是为了说明我想要获取的位置,并且我坚持如何传递给do.call-rbind,它应该基于元素名称将特定于主体的元素绑定为新列表元素放在一起,同时分配一个新的变量。

对我来说,这是一个有点模糊的任务,最接近我得到的是rlist包。 This问题是相关的,但使用unique来识别元素,而在我的情况下,它似乎更多的正则表达式问题。

我很乐意甚至如何使用谷歌,任何关键字进行进一步的研究等

+1

如果您提供了一些真实的数据框名称,有人试图帮助您可以为您编写更准确的正则表达式。 –

+0

我认为在更抽象的层面上留下正则表达式问题会让我的问题变得混乱。当然,stackoverflow再次证明对周围的人有帮助。我会在下面处理你的答案,并回来:) – leokrkr

回答

0

听起来好像你做了很多体操的,因为你心里有一个具体形式。我想建议的是首先尝试使数据tidy。在没有阅读链接的情况下,快速总结就是将您的数据放入一个数据框中,并且可以轻松处理。

快速版本的答案(这里我用lst代替list的名称,以避免混淆内置list)的是要做到这一点:

do.call(rbind, 
    lapply(seq(lst), function(i) { 
    lst[[i]]$type <- names(lst)[i]; lst[[i]] 
    }) 
) 

这将完成是创建一个单一的数据框,其中包含“type”列,其中包含该行出现的列表项的名称。

使用您的初始数据的略微简化的版本:

lst <- list(A1=data.frame(x=rnorm(5)), A2=data.frame(x=rnorm(3)), B=data.frame(x=rnorm(5))) 
lst 
$A1 
      x 
1 1.3386071 
2 1.9875317 
3 0.4942179 
4 -0.1803087 
5 0.3094100 

$A2 
      x 
1 -0.3388195 
2 1.1993115 
3 1.9524970 

$B 
      x 
1 -0.1317882 
2 -0.3383545 
3 0.8864144 
4 0.9241305 
5 -0.8481927 

,然后应用的神奇功能

df <- do.call(rbind, 
    lapply(seq(lst), function(i) { 
    lst[[i]]$type <- names(lst)[i]; lst[[i]] 
    }) 
) 
df 
      x type 
1 1.3386071 A1 
2 1.9875317 A1 
3 0.4942179 A1 
4 -0.1803087 A1 
5 0.3094100 A1 
6 -0.3388195 A2 
7 1.1993115 A2 
8 1.9524970 A2 
9 -0.1317882 B 
10 -0.3383545 B 
11 0.8864144 B 
12 0.9241305 B 
13 -0.8481927 B 

从这里我们可以处理我们的心灵内容;通过像df$subject <- gsub("[0-9]*", "", df$type)这样的操作来提取type的非数字部分,而像split这样的工具可用于生成您在问题中提到的子列表。

此外,一旦它在这种形式下,你可以使用功能,如byaggregate或库,例如dplyrdata.table来进行数据分析做更先进的拆分申请,结合操作。

+0

只要我的名声不允许upvotes,我会在这里留下我的感谢。我需要更多的时间来处理你的答案,而不是你们写的! – leokrkr

2

从您提供的数据说明:我们做的正则表达式调用

subj <- sub("[A-Z]*", "", names(lst)) 
newlst <- Map(function(x, y) {x[,"class"] <- y;x}, lst, subj) 

第一隔离将在class列中的数字。在这种情况下,我匹配大写字母并删除它们,留下数字。因此,"A1"变成"1"。请注意,真实姓名将表示不同的正则表达式模式。

然后我们使用Map为每个数据帧创建一个新列并保存到名为newlst的新列表中。 Map接受每个参数的第一个元素并执行该函数,然后继续处理每个对象元素。因此,首先使用lst中的第一个数据帧和subj中的第一个数据帧。我使用的匿名函数是function(x,y) {x[, "class"] <- y; x}。它有两个参数。第一个是数据框,第二个是列值。

现在往前走容易得多。我们可以创建一个名为uniq.nmes的向量来获取我们将要组合的数据帧的名称。其中"A1"将变为"A"。然后我们就可以rbind在那场比赛:

uniq.nmes <- unique(sub("\\d", "", names(lst))) 
lapply(uniq.nmes, function(x) { 
    do.call(rbind, newlst[grep(x, names(newlst))]) 
}) 
# [[1]] 
#  x y class 
# A1.1 1 79  1 
# A1.2 30 13  1 
# A2.1 90 39  2 
# A2.2 43 22  2 
# 
# [[2]] 
#  x y class 
# B1.1 54 59  1 
# B1.2 83 90  1 
# B2.1 85 36  2 
# B2.2 91 28  2 

数据

A1 <- data.frame(x=sample(1:100,2),y=sample(1:100,2)) 
A2 <- data.frame(x=sample(1:100,2),y=sample(1:100,2)) 
B1 <- data.frame(x=sample(1:100,2),y=sample(1:100,2)) 
B2 <- data.frame(x=sample(1:100,2),y=sample(1:100,2)) 

lst <- list(A1=A1,A2=A2,B1=B1,B2=B2)