如何解决R中的“自然”程序问题的高效函数编程使用mapply
| R中的一个常见用例(至少对我而言)是识别数据帧中的观测值,这些观测值具有某些特征,该特征取决于其他观测值的某些子集中的值。 为了使自己更加自信,假设我有一些工人(由WorkerId索引) 具有关联的“迭代”: raw <- data.frame(WorkerId=c(1,1,2,3,3),Iteration = c(1,4,4))
并且我最终希望为每个工作者分配数据帧以排除“最后一次”迭代(通过创建“删除”布尔值)。我可以编写一个函数来做到这一点:
raw$remove <- mapply(function(wid,iter){
iter==max(raw$Iteration[raw$WorkerId==wid])},raw$WorkerId,raw$Iteration)
> raw$remove
[1] FALSE FALSE FALSE TRUE FALSE FALSE FALSE TRUE FALSE FALSE FALSE TRUE
但这随着数据帧变大而变得非常慢(大概是因为我不必要地为每个观察值计算最大值)。
我的问题是,在函数式编程风格中,这样做的更有效(惯用)方式是什么?它是先创建一个WorkerId to Max值字典,然后将其用作对每个观察值进行操作的另一个函数中的参数吗?
解决方法
IMO的“最自然的方式”是split-lapply-rbind方法。首先,将split()放入一组列表中,然后对处理规则进行lapply()处理(在这种情况下,删除最后一行),然后将它们重新绑定在一起。作为嵌套的一组函数调用,它们都是可行的。内部的两个步骤在此处说明,最后的一线显示在底部:
> lapply( split(raw,raw$WorkerId),function(x) x[-NROW(x),] )
$`1`
WorkerId Iteration
1 1 1
2 1 2
3 1 3
$`2`
WorkerId Iteration
5 2 1
6 2 2
7 2 3
$`3`
WorkerId Iteration
9 3 1
10 3 2
11 3 3
do.call(rbind,lapply( split(raw,] ) )
Hadley Wickham开发了各种各样的工具(plyr
软件包),可以将这一策略扩展到更多任务。
, 对于提出的!rev(duplicated(rev(raw$WorkerId)))
或更佳的具体问题,按照查尔斯的建议,5ѭ
, 这种情况是为使用plyr
软件包量身定制的。
ddply(raw,.(WorkerId),function(df) df[-NROW(df),])
它产生输出
WorkerId Iteration
1 1 1
2 1 2
3 1 3
4 2 1
5 2 2
6 2 3
7 3 1
8 3 2
9 3 3
, subset(raw,Iteration != ave(Iteration,WorkerId,FUN=max))
, remove <- with(raw,as.logical(ave(Iteration,FUN=function(x) c(rep(TRUE,length(x)-1),FALSE)))))
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。