我想选择数据框中每个组的前(2,3,0,4)行。
> f<-data.frame(group=c(1,1,1,2,2,3,4),y=c(1:7))
>
> group y
> 1 1
> 1 2
> 1 3
> 2 4
> 2 5
> 3 6
> 4 7
并获得以下数据框:
group y
1 1
1 2
2 4
2 5
4 7
我尝试使用by
和head
,但是head
不接受向量。
谢谢你的帮助。
使用更传统的lapply
函数:
k <- c(2,3,0,4)
fs <- split(f, f$group)
do.call(rbind,lapply(seq_along(k), function(i) head(fs[[i]], k[i])))
结果是:
group y
1 1 1
2 1 2
4 2 4
5 2 5
7 4 7
plyr
:library(plyr)
rows <- c(2,3,0,4)
ddply(f,.(group),function(x)head(x,rows[x[1,1]]))
group y
1 1 1
2 1 2
3 2 4
4 2 5
5 4 7
误解问题,现已更新答案。
带索引的函数版本。
fun1 <- function(){
idx <- c(0,which(diff(f$group)!=0))+1
idx2 <- unlist(lapply(1:length(nf),function(x) seq.int(from=idx[x],length.out=nf[x])),use.names=F)
f1 <- f[idx2,]
return(f1)
}
fun2 <- function(){
ddply(f,.(group),function(x) head(x,nf[x[1,1]]))
}
测试数据(建议问题作者的大小)
f<-data.frame(group=sample(1:1000,50000,T),y=c(1:50000))
f <- f[order(f$group),]
nf <- rpois(length(unique(f$group)),3)
system.time(fun1()) system.time(fun2())
在我的系统上,fun1的速度大约比fun2快60倍。
split
会创建一个新的数据对象,如果是这样的话,而且f
非常大,那可能需要一段时间。如果它被证明太慢了,Hadley的plyr
包据说可以更快地处理一些类似的事情,你可以尝试一下(就像Sacha的解决方案)。如果你只想要每个组中的几行,也完全有可能通过精心编写的for循环来改进这个问题。另一个可能性是简化split
,因为只需要保留y
,但这会使记录变得复杂。 - Aaron left Stack Overflow