#r #dplyr #data-cleaning #data-wrangling
#r #dplyr #очистка данных #перебор данных
Вопрос:
Я буду использовать встроенные chickwts
данные в качестве примера.
Вот данные, существует 5 типов каналов.
> head(chickwts)
weight feed
1 179 horsebean
2 160 horsebean
3 136 horsebean
4 227 horsebean
5 217 horsebean
6 168 horsebean
> table(chickwts$feed)
casein horsebean linseed meatmeal soybean sunflower
12 10 12 11 14 12
Мне нужны верхние строки по весу для каждого типа подачи. Однако мне нужно другое число для каждого типа подачи? Например,
top_n_feed <-
c(
"casein" = 3,
"horsebean" = 5,
"linseed" = 3,
"meatmeal" = 6,
"soybean" = 3,
"sunflower" = 2
)
Как я могу это сделать с помощью dplyr
?
Чтобы получить верхние n
строки каждого типа подачи по весу, я могу использовать код, как показано ниже, но я не уверен, как расширить это до другого числа для каждого типа подачи.
chickwts %>%
group_by(feed) %>%
slice_max(order_by = weight, n = 5)
Ответ №1:
На самом деле это не то, что dplyr
легко назвать. Я бы рекомендовал объединить данные и затем отфильтровать.
tibble(feed=names(top_n_feed), topn=top_n_feed) %>%
inner_join(chickwts) %>%
group_by(feed) %>%
arrange(desc(weight), .by_group=TRUE) %>%
filter(row_number() <= topn) %>%
select(-topn)
Комментарии:
1. Действительно, пропустил часть о порядке по весам. Это точно покроет его.
Ответ №2:
Каждый раз, когда у вас есть именованный список, подумайте purrr::imap
. Избегайте объединений, если это не требуется, особенно при работе в масштабе.
library(dplyr)
library(purrr)
top_n_feed <- c(
"casein" = 3,
"horsebean" = 5,
"linseed" = 3,
"meatmeal" = 6,
"soybean" = 3,
"sunflower" = 2
)
imap_dfr(top_n_feed, ~ filter(chickwts, feed %in% .y) %>%
slice_max(order_by = weight, n = .x))
weight feed
1 404 casein
2 390 casein
3 379 casein
4 227 horsebean
5 217 horsebean
6 179 horsebean
7 168 horsebean
8 160 horsebean
9 309 linseed
10 271 linseed
11 260 linseed
12 380 meatmeal
13 344 meatmeal
14 325 meatmeal
15 315 meatmeal
16 303 meatmeal
17 263 meatmeal
18 329 soybean
19 327 soybean
20 316 soybean
21 423 sunflower
22 392 sunflower
Ответ №3:
Другой способ с использованием split
и map2
:
library(dplyr)
library(purrr)
chickwts %>%
filter(feed %in% names(top_n_feed)) %>%
split(.$feed) %>%
map2_dfr(top_n_feed[names(.)], ~slice_max(.x, order_by = weight, n = .y))
Комментарии:
1. Классный подход — не могли бы вы объяснить синтаксис .$feed в
split
?2. Это синтаксис для подмножества столбцов data.frame.
.
представляет data.frame из файла %>% (результат последнего шага).
Ответ №4:
Введите top_n_feed
chickwts
dataframe и выберите верхние n
строки для каждой группы.
library(dplyr)
tibble::enframe(top_n_feed, name = 'feed') %>%
left_join(chickwts, by = 'feed') %>%
group_by(feed) %>%
top_n(first(value), weight)
# feed value weight
# <chr> <dbl> <dbl>
# 1 casein 3 390
# 2 casein 3 379
# 3 casein 3 404
# 4 horsebean 5 179
# 5 horsebean 5 160
# 6 horsebean 5 227
# 7 horsebean 5 217
# 8 horsebean 5 168
# 9 linseed 3 309
#10 linseed 3 260
# … with 12 more rows
По какой-то причине я не смог выполнить slice_sample
работу для этого примера.