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 <- group_by(df, A)
filter(df.g, x == min(x))
как и ожидалось, все минимумы будут вернулся:
Source: local data frame [6 x 3]
Groups: A
A x y
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 x y
1 A 1 -1.04584335
2 B 2 0.79600971
3 C 5 -0.08655151
Q: есть ли способ приблизиться к этому в dplyr? (по производительности)
6 ответов:
просто для полноты картины: вот окончательный
dplyr
решение, полученное из комментариев @hadley и @Arun:library(dplyr) df.g <- group_by(df, A) filter(df.g, rank(x, ties.method="first")==1)
для чего это стоит, вот такой
data.table
решение, для тех, кто может быть заинтересован:# 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_number
в сочетании сgroup_by
.row_number
обрабатывает связи, присваивая ранг не только по значению, но и по относительному порядку внутри вектора. Чтобы получить первую строку каждой группы с минимальным значениемx
:df.g <- group_by(df, A) filter(df.g, row_number(x) == 1)
для получения дополнительной информации см. dplyr виньетка на окне функции.