dplyr filter:获取具有最小variables的行,但只有第一个如果多个最小值

我想用dplyr做一个分组filter,在每个组中只有那个返回variablesx的最小值的行。

我的问题是:正如所料,在多重最小值的情况下返回所有具有最小值的行。 但就我而言,如果存在多个最小值, 我只想要第一行

这是一个例子:

 df <- data.frame( A=c("A", "A", "A", "B", "B", "B", "C", "C", "C"), x=c(1, 1, 2, 2, 3, 4, 5, 5, 5), y=rnorm(9) ) library(dplyr) df.g <- group_by(df, A) filter(df.g, x == min(x)) 

正如预期的那样,所有的最小值都会返回

 Source: local data frame [6 x 3] Groups: A A xy 1 A 1 -1.04584335 2 A 1 0.97949399 3 B 2 0.79600971 4 C 5 -0.08655151 5 C 5 0.16649962 6 C 5 -0.05948012 

随着ddply,我会以这种方式来处理任务:

 library(plyr) ddply(df, .(A), function(z) { z[z$x == min(z$x), ][1, ] }) 

…工作原理:

  A xy 1 A 1 -1.04584335 2 B 2 0.79600971 3 C 5 -0.08655151 

问:在dplyr中有没有办法解决这个问题? (由于速度原因)

更新

在dplyr> = 0.3的情况下,您可以结合使用slice函数which.min ,这将是我最喜欢的任务:

 df %>% group_by(A) %>% slice(which.min(x)) #Source: local data frame [3 x 3] #Groups: A # # A xy #1 A 1 0.2979772 #2 B 2 -1.1265265 #3 C 5 -1.1952004 

原始答案

对于示例数据,也可以使用两个filter

 group_by(df, A) %>% filter(x == min(x)) %>% filter(1:n() == 1) 

只是为了完整:这是最终的dplyr解决scheme,来自@hadley和@Arun的评论:

 library(dplyr) df.g <- group_by(df, A) filter(df.g, rank(x, ties.method="first")==1) 

对于那些可能感兴趣的人来说,这是一个data.table解决scheme。

 # approach with setting keys dt <- as.data.table(df) setkey(dt, A,x) dt[J(unique(A)), mult="first"] # without using keys dt <- as.data.table(df) dt[dt[, .I[which.min(x)], by=A]$V1] 

这可以通过使用row_numbergroup_by组合来完成。 row_number通过不仅通过值而且通过向量内的相对顺序分配等级来处理关系。 要得到每个组的最小值为x的第一行:

 df.g <- group_by(df, A) filter(df.g, row_number(x) == 1) 

有关更多信息,请参阅窗口函数上的dplyr 小插曲 。

我喜欢sqldf简单..

 sqldf("select A,min(X),y from 'df.g' group by A") 

输出:

 A min(X) y 1 A 1 -1.4836989 2 B 2 0.3755771 3 C 5 0.9284441 

另一种方法来做到这一点:

 set.seed(1) x <- data.frame(a = rep(1:2, each = 10), b = rnorm(20)) x <- dplyr::arrange(x, a, b) dplyr::filter(x, !duplicated(a)) 

结果:

  ab 1 1 -0.8356286 2 2 -2.2146999 

也可以很容易地适应每个组获得最大价值的行。