我对应用函数有一个小问题。 例如,我有:
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'必须是一种更容易的方式,但是我无法使它成功。
请帮忙
答案 0 :(得分:3)
如何合并lapply
和tapply
:
lapply(l, function(i) tapply(i$C1, i$B1, min))
$a
1 2
5 7
$b
3 4
3 10
考虑多个操作的技巧是将任务拆分为多个位。所以,
每个C1
的最低B1
。我们如何为单个数据框执行此操作?
i = l[[1]]
tapply(i$C1, i$B1, min)
列表中的每个元素?只需使用lapply
:
lapply(l, function(i) tapply(i$C1, i$B1, min))
如果您无法执行第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)})