2012-10-18 44 views
3

使用plyrllply优于lapply的优点是它保留了列表名称。有关说明,请参阅?llply。我喜欢这个功能,但似乎无法让它在嵌套列表的情况下工作。例如:如何在使用嵌套列表时如何保留列表名称?

library(plyr) 
m <- as.list(1:2) 
names(m) <- c('M1', 'M2') 
foo <- list(m, m) 
names(foo) <- paste0("R", 1:2) 


result <- ldply(foo, function(x){ 
     ldply(x, function(z) { data.frame(a=z, b= z^2)}) 
}) 
> result 
    .id a b 
1 M1 1 1 
2 M2 2 4 
3 M1 1 1 
4 M2 2 4 

# if I don't operate on the inner list, I can preserve the outer list's names 
result2 <- ldply(foo, function(x){ 
    data.frame(a = x[[1]], b = x[[1]]^2) 
    }) 
> result2 
  .id a b 
1  R1 1 1 
2  R2 1 1 

注意result不含R1R2(这将被添加作为.id如果我没有的foo各元素中嵌套列表上操作,就与result2的情况下)。我如何确保在嵌套列表上工作时添加外部列表名称?

+0

注:我知道,我能解决这个事后(如读取FOO的名称和复制每一个由子列表的长度,并补充说,作为一个新列)。但我希望能够理解为什么我不能按照设计运行。 – Maiasaura

回答

5

看来,列名的问题是:

result <- ldply(foo, function(x){ 
    df <- ldply(x, function(z) { data.frame(a=z, b= z^2)}) 
    names(df)[1] <- ".id2"; df 
}) 
result 
    .id .id2 a b 
1 R1 M1 1 1 
2 R1 M2 2 4 
3 R2 M1 1 1 
4 R2 M2 2 4 
+0

谢谢,很好。我想知道我是否应该将此作为plyr的缺陷发布。这将是一个快速的解决方案,以检查是否存在名为'.id'的列,然后创建一个新列。 – Maiasaura

+0

是的,请提交错误报告。 – hadley

+1

完成:https://github.com/hadley/plyr/issues/107 – Maiasaura

3

的问题是,如果已经有一个ldply不分配给.id变量。如果你看看你的内心ldply的一个结果一次,它是好的:

> ldply(foo[[1]], function(z) { data.frame(a=z, b= z^2)}) 
    .id a b 
1 M1 1 1 
2 M2 2 4 

重新命名它的方式,它按预期工作。

result <- ldply(foo, function(x){ 
    rename(ldply(x, function(z) { data.frame(a=z, b= z^2)}), 
      c(".id" = ".id2")) 
}) 

> result 
    .id .id2 a b 
1 R1 M1 1 1 
2 R1 M2 2 4 
3 R2 M1 1 1 
4 R2 M2 2 4 
+0

谢谢布赖恩,看起来像你和朱利叶斯想出了同样的解决方案。干杯。 – Maiasaura