dplyr筛选器:获取具有最小变量的行,但如果有多个最小值,则仅获取第一行
我想使用dplyr筛选器:获取具有最小变量的行,但如果有多个最小值,则仅获取第一行,r,dplyr,R,Dplyr,我想使用dplyr创建一个分组过滤器,在每个组中只返回最小值为变量x的行 我的问题是:正如预期的那样,在多个最小值的情况下,返回具有最小值的所有行。但是在我的例子中,如果存在多个极小值,我只想要第一行 下面是一个例子: 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 <
dplyr
创建一个分组过滤器,在每个组中只返回最小值为变量x
的行
我的问题是:正如预期的那样,在多个最小值的情况下,返回具有最小值的所有行。但是在我的例子中,如果存在多个极小值,我只想要第一行
下面是一个例子:
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))
有了ddply,我将以这种方式完成任务:
library(plyr)
ddply(df, .(A), function(z) {
z[z$x == min(z$x), ][1, ]
})
。。。有效的方法是:
A x y
1 A 1 -1.04584335
2 B 2 0.79600971
3 C 5 -0.08655151
Q:在dplyr中是否有一种方法可以实现这一点?(出于速度原因)对于它的价值,这里有一个
数据表
解决方案,供可能感兴趣的人使用:
# 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]
#使用设置键接近
dt只是为了完整性:这里是最终的dplyr
解决方案,来自@hadley和@Arun的评论:
library(dplyr)
df.g <- group_by(df, A)
filter(df.g, rank(x, ties.method="first")==1)
库(dplyr)
df.g更新
当dplyr>=0.3时,您可以将slice
功能与which.min
结合使用,这将是我最喜欢的执行此任务的方法:
df %>% group_by(A) %>% slice(which.min(x))
#Source: local data frame [3 x 3]
#Groups: A
#
# A x y
#1 A 1 0.2979772
#2 B 2 -1.1265265
#3 C 5 -1.1952004
原始答案
对于样本数据,也可以在每个样本数据之后使用两个过滤器
:
group_by(df, A) %>%
filter(x == min(x)) %>%
filter(1:n() == 1)
这可以通过使用行编号
与分组依据
组合来实现<代码>行编号
通过不仅根据值,而且根据向量内的相对顺序分配秩来处理关系。要获取最小值为x
的每组第一行:
df.g <- group_by(df, A)
filter(df.g, row_number(x) == 1)
df.g我喜欢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))
也可以很容易地调整以获得每组中具有最大值的行 来这里是想找到一种方法,用一个以上的。我相信,这会让排名倒数第十的球队最终打破平局
df.g %>%
top_n(-10,row_number(x))
dplyr
提供了slice\u min
函数,该函数使用参数执行任务,参数=FALSE
library(dplyr)
df %>%
group_by(A) %>%
slice_min(x, with_ties = FALSE)
输出:
# A tibble: 3 x 3
# Groups: A [3]
A x y
<fct> <dbl> <dbl>
1 A 1 0.273
2 B 2 -0.462
3 C 5 1.08
#一个tible:3 x 3
#分组:A[3]
A x y
1A 10.273
2b2-0.462
3 C 5 1.08
过滤器(df.g,秩(x)=1)
?@FelixS,秩(x)=1
是否给出了所需的结果?@hadley,1)我认为最小秩
在这里没有帮助。他需要第一个最小值(查看plyr
solution)。2) 在您编写的任何编程语言中,rank
(ties=min,max,first等)的算法复杂度将比只计算min
@Arun:True,只有rank(x,ties.method=“first”)==1
起作用,因为min和min\u-rank不区分多个极小值。@hadley,我仍然不明白这是怎么让你考虑<代码>的。MIN <代码>是早熟的优化。好吧,这是一个自然的选择,读起来很好,很容易理解,速度也很快。我发现do(head)
更容易阅读,df%%>%group\u by(a)%%>%filter(x==min(x))%%>%do(head(,1))
@baptiste看起来确实不错(但是,当我运行它时,我收到一条错误消息error:需要一个值
)-你知道为什么吗?不确定,也许我们使用的是不同的版本;我有dplyr_0.2,magrittr_1.0.0
Ok,所以问题是我仍然在运行dplyr 0.1.3。我更愿意在这里使用top\n
,但由于关系密切,这种方法可能是明显的赢家-在性能方面(与arrange%>%slice
相比)肯定是如此。这是我最喜欢的答案!
library(dplyr)
df %>%
group_by(A) %>%
slice_min(x, with_ties = FALSE)
# A tibble: 3 x 3
# Groups: A [3]
A x y
<fct> <dbl> <dbl>
1 A 1 0.273
2 B 2 -0.462
3 C 5 1.08