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

jke*_*ger 20 r dataframe

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

例如,我想转换它

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

进入:

    x  y  z
1   1 11 19
2   2 12 18
3   4 13 17
Run Code Online (Sandbox Code Playgroud)

我目前正在使用聚合来执行此操作,但是使用更多数据时性能是不可接受的:

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

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

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

Dir*_*tel 28

也许duplicated()可以帮助:

R> d[ !duplicated(d$x), ]
  x  y  z
1 1 10 20
3 2 12 18
4 4 13 17
R> 
Run Code Online (Sandbox Code Playgroud)

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

R> ddply(d, "x", function(z) tail(z,1))
  x  y  z
1 1 11 19
2 2 12 18
3 4 13 17
R> 
Run Code Online (Sandbox Code Playgroud)

这里plyr确实找到独特的子集,遍历它们并应用提供的函数的辛勤工作-它简单的返回最后一组观察块中的z使用tail(z, 1).


Ian*_*ows 13

只是为Dirk提供的内容添加一点...... duplicated有一个fromLast参数可以用来选择最后一行:

d[ !duplicated(d$x,fromLast=TRUE), ]
Run Code Online (Sandbox Code Playgroud)


mne*_*nel 11

这是一个data.table解决方案,它将为大型数据集提供时间和内存效率

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
Run Code Online (Sandbox Code Playgroud)

  • `独特(DT,由= "×",fromLast = TRUE)`是现在简单并且比`DT [!复制(X,fromLast = TRUE)]`和`DT [J(唯一的(X)),多重峰更快= '最后']` (2认同)

sbh*_*bha 5

有几个选项使用dplyr

library(dplyr)
df %>% distinct(x, .keep_all = TRUE)
df %>% group_by(x) %>% filter(row_number() == 1)
df %>% group_by(x) %>% slice(1)
Run Code Online (Sandbox Code Playgroud)

您可以将多个列与distinct()and一起使用group_by()

df %>% distinct(x, y, .keep_all = TRUE)
Run Code Online (Sandbox Code Playgroud)

如果存在日期或其他顺序字段并且您希望确保保留最新的观察结果,则 and 方法可能很有用,如果您想避免联系,则该方法可能很有用group_by()filter()slice()

df %>% group_by(x) %>% filter(date == max(date)) %>% slice(1)
Run Code Online (Sandbox Code Playgroud)