Как выбрать строки с максимальными значениями в каждой группе с помощью dplyr?
Я хотел бы выбрать строку с максимальным значением в каждой группе с dplyr.
Во-первых, я генерирую некоторые случайные данные, чтобы показать свой вопрос
set.seed(1)
df <- expand.grid(list(A = 1:5, B = 1:5, C = 1:5))
df$value <- runif(nrow(df))
В plyr я могу использовать пользовательскую функцию для выбора этой строки.
library(plyr)
ddply(df, .(A, B), function(x) x[which.max(x$value),])
В dplyr я использую этот код для получения максимального значения, но не для строк с максимальным значением (в этом случае используется столбец C).
library(dplyr)
df %>% group_by(A, B) %>%
summarise(max = max(value))
Как я мог это достичь? Спасибо за любое предложение.
sessionInfo()
R version 3.1.0 (2014-04-10)
Platform: x86_64-w64-mingw32/x64 (64-bit)
locale:
[1] LC_COLLATE=English_Australia.1252 LC_CTYPE=English_Australia.1252
[3] LC_MONETARY=English_Australia.1252 LC_NUMERIC=C
[5] LC_TIME=English_Australia.1252
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] dplyr_0.2 plyr_1.8.1
loaded via a namespace (and not attached):
[1] assertthat_0.1.0.99 parallel_3.1.0 Rcpp_0.11.1
[4] tools_3.1.0
Ответы
Ответ 1
Попробуйте следующее:
result <- df %>%
group_by(A, B) %>%
filter(value == max(value)) %>%
arrange(A,B,C)
Кажется, работает:
identical(
as.data.frame(result),
ddply(df, .(A, B), function(x) x[which.max(x$value),])
)
#[1] TRUE
Как указано @docendo в комментариях, slice
может быть здесь предпочтительнее в соответствии с ответом @RoyalITS ниже, если вы строго хотите только 1 строку на группу. Этот ответ вернет несколько строк, если их несколько с одинаковым максимальным значением.
Ответ 2
Вы можете использовать top_n
df %>% group_by(A, B) %>% top_n(n=1)
Это будет ранжироваться по последнему столбцу (value
) и вернуть верхние строки n=1
.
В настоящее время вы не можете изменить это значение по умолчанию, не вызывая ошибки (см. https://github.com/hadley/dplyr/issues/426)
Ответ 3
df %>% group_by(A,B) %>% slice(which.max(value))
Ответ 4
Это более подробное решение обеспечивает больший контроль над тем, что происходит в случае двойного максимального значения (в этом примере он будет принимать одну из соответствующих строк случайным образом)
library(dplyr)
df %>% group_by(A, B) %>%
mutate(the_rank = rank(-value, ties.method = "random")) %>%
filter(the_rank == 1) %>% select(-the_rank)
Ответ 5
В целом, я думаю, что вы можете получить "верх" строк, которые отсортированы в данной группе.
Для случая, когда одно значение имеет максимальное значение, вы отсортировали только по одному столбцу. Однако часто полезно иерархически сортировать по нескольким столбцам (например: столбец даты и столбец времени).
# Answering the question of getting row with max "value".
df %>%
# Within each grouping of A and B values.
group_by( A, B) %>%
# Sort rows in descending order by "value" column.
arrange( desc(value) ) %>%
# Pick the top 1 value
slice(1) %>%
# Remember to ungroup in case you want to do further work without grouping.
ungroup()
# Answering an extension of the question of
# getting row with the max value of the lowest "C".
df %>%
# Within each grouping of A and B values.
group_by( A, B) %>%
# Sort rows in ascending order by C, and then within that by
# descending order by "value" column.
arrange( C, desc(value) ) %>%
# Pick the one top row based on the sort
slice(1) %>%
# Remember to ungroup in case you want to do further work without grouping.
ungroup()
Ответ 6
Для меня это помогло подсчитать количество значений на группу. Скопируйте таблицу подсчета в новый объект. Затем отфильтруйте максимум группы на основе первой характеристики группировки. Например:
count_table <- df %>%
group_by(A, B) %>%
count() %>%
arrange(A, desc(n))
count_table %>%
group_by(A) %>%
filter(n == max(n))
или же
count_table %>%
group_by(A) %>%
top_n(1, n)