如何拆分data.frame列表并将函数应用于一列?

时间:2013-02-12 09:57:30

标签: r list dataframe lapply

我对应用函数有一个小问题。 例如,我有:

l <- list(a = data.frame(A1=rep(10,5),B1=c(1,1,1,2,2),C1=c(5,10,20,7,30)),
          b = data.frame(A1=rep(20,5),B1=c(3,3,4,4,4),C1=c(3,5,10,20,30)))

我想为每个B1找到最小C1。结果应该是

$a
  A1 B1 C1
  10  1  5
  10  2  7

$b
  A1 B1 C1
  20  3  3
  20  4  10

我知道怎么用'for'来做,但是'lapply'必须是一种更容易的方式,但是我无法使它成功。

请帮忙

4 个答案:

答案 0 :(得分:3)

如何合并lapplytapply

lapply(l, function(i) tapply(i$C1, i$B1, min))
$a
1 2 
5 7 

$b
3  4 
3 10 

考虑多个操作的技巧是将任务拆分为多个位。所以,

  1. 每个C1的最低B1。我们如何为单个数据框执行此操作?

    i = l[[1]]
    tapply(i$C1, i$B1, min)
    
  2. 列表中的每个元素?只需使用lapply

    lapply(l, function(i) tapply(i$C1, i$B1, min))
    
  3. 如果您无法执行第1步,则无法管理第2步。

答案 1 :(得分:3)

最近屈服于data.table包的警笛歌曲及其多功能性和速度的组合,我做了另外一个解决方案:

library(data.table)
lapply(l, function(dat) {
    data.table(dat, key="B1,C1")[list(unique(B1)), mult="first"]
})

如果保留原始列顺序很重要,由于某种原因,data.table()调用可能会被setcolorder(..., names(dat))包裹。

答案 2 :(得分:2)

这是另一种符合您所需输出的方法:

lapply(l, function(x) {
  temp <- ave(x[["C1"]], x["B1"], FUN = min)
  x[x[["C1"]] == temp, ]
})
# $a
#   A1 B1 C1
# 1 10  1  5
# 4 10  2  7
# 
# $b
#   A1 B1 C1
# 1 20  3  3
# 3 20  4 10

答案 3 :(得分:0)

您也可以从plyr / reshape2工具箱中尝试llply + dcast:

library(reshape2)
library(plyr)

    l <- list(a = data.frame(A1=rep(10,5),B1=c(1,1,1,2,2),C1=c(5,10,20,7,30)),
              b = data.frame(A1=rep(20,5),B1=c(3,3,4,4,4),C1=c(3,5,10,20,30)))

    llply(l, function (x) {dcast (x, A1+B1~., value.var="C1", min)})