通过为每个组select一行来折叠数据框

我试图通过删除特定列中具有相同值的每组行中除了一行以外的所有行来折叠数据框。 换句话说,每组的第一行。

例如,我想转换这个

> d = data.frame(x=c(1,1,2,4),y=c(10,11,12,13),z=c(20,19,18,17)) > d xyz 1 1 10 20 2 1 11 19 3 2 12 18 4 4 13 17 

进入这个:

  xyz 1 1 11 19 2 2 12 18 3 4 13 17 

目前我正在使用聚合来完成这个任务,但是如果有更多的数据,性能是不可接受的:

 > d.ordered = d[order(-d$y),] > aggregate(d.ordered,by=list(key=d.ordered$x),FUN=function(x){x[1]}) 

我尝试过使用与此处相同的函数参数进行split / unsplit,但是unsplit抱怨重复的行号。

有可能吗? 是否有一个R语言将rle的长度向量转换为开始每次运行的行的索引,然后我可以使用这些索引将这些行从数据框中提取出来?

也许duplicated()可以帮助:

 R> d[ !duplicated(d$x), ] xyz 1 1 10 20 3 2 12 18 4 4 13 17 R> 

编辑 Shucks,没关系。 这是每个重复块中的第一个,你想要最后一个。 所以这里是使用plyr的另一个尝试:

 R> ddply(d, "x", function(z) tail(z,1)) xyz 1 1 11 19 2 2 12 18 3 4 13 17 R> 

在这里plyr做了很多努力find唯一的子集,循环它们并应用提供的函数 – 它只是使用tail(z, 1)返回块z的最后一组观测值。

只需要添加一些什么Dirk提供… duplicated有一个fromLast参数,您可以用来select最后一行:

 d[ !duplicated(d$x,fromLast=TRUE), ] 

这里是一个data.table解决scheme,这将是大数据集的时间和内存效率

 library(data.table) DT <- as.data.table(d) # convert to data.table setkey(DT, x) # set key to allow binary search using `J()` DT[J(unique(x)), mult ='last'] # subset out the last row for each x DT[J(unique(x)), mult ='first'] # if you wanted the first row for each x