k_th самый маленький элемент на группу в R - PullRequest
3 голосов
/ 11 мая 2019

У меня есть таблица данных, dt, которая выглядит как

   location year value
       NYC 2026     1
       NYC 2026     2
       NYC 2026     3
       NYC 2026     4
       NYC 2026     5
        LA 2026     6
        LA 2026     7
        LA 2026     8
        LA 2026     9
        LA 2026    10

Я бы хотел сгруппировать их по city и year и найти 2-й наименьший элемент в столбце value для каждой группы, где желаемый результат выглядит следующим образом:

   location year value
        NYC  2026     2
         LA  2026     7

dt %>% grou_by(location, year) %>% nth(value, 2)

Не будет работать.Любая помощь приветствуется.

Приведенную выше таблицу данных можно создать:

dt <- structure(list(location = c("NYC", "NYC", "NYC","NYC", "NYC", 
                                   "LA", "LA", "LA", "LA", "LA"), 
                 year = c(2026, 2026, 2026, 2026, 2026,
                          2026, 2026, 2026, 2026, 2026),
                 value = c(1, 2, 3, 4, 5,
                           6, 7, 8, 9, 10)),
                 class = "data.table", 
                 row.names = c(NA, -10L))

Ответы [ 3 ]

6 голосов
/ 11 мая 2019

Одна dplyr возможность может быть:

df %>%
 group_by(location) %>%
 arrange(value) %>%
 slice(2)

Здесь она группируется по столбцу «location», упорядочивает значения в соответствии со столбцом «value», а затем сохраняет второй элемент.

  location  year value
  <chr>    <int> <int>
1 LA        2026     7
2 NYC       2026     2

Или, если значения в столбце «значение» могут быть дубликатами, вы можете сделать:

df %>%
 group_by(location) %>%
 distinct(value, .keep_all = TRUE) %>%
 arrange(value) %>%
 slice(2)

Или использовать filter() вместо slice():

df %>%
 group_by(location) %>%
 arrange(value) %>%
 filter(row_number() == 2)

То же самое касается и возможных дубликатов:

df %>%
 group_by(location) %>%
 distinct(value, .keep_all = TRUE) %>%
 arrange(value) %>%
 filter(row_number() == 2)

Или с использованием filter() и dense_rank():

df %>%
 group_by(location) %>%
 filter(dense_rank(value) == 2)

То же касается и возможных дубликатов:

df %>%
 group_by(location) %>%
 distinct(value, .keep_all = TRUE) %>%
 filter(dense_rank(value) == 2)
4 голосов
/ 11 мая 2019

Использование summarize для работы с group_by:

> dt %>% group_by(location, year) %>% arrange(value) %>%  summarize(value = nth(value, 2))
# A tibble: 2 x 3
# Groups:   location [2]
  location  year value
  <chr>    <dbl> <dbl>
1 LA        2026     7
2 NYC       2026     2
1 голос
/ 11 мая 2019

Поскольку вам нужен только второй элемент, частичная сортировка не должна быть исключена.Я не знаю, поддерживается ли он dplyr или data.table, но это с базовой сортировкой R (с ограниченными параметрами), например.что-то вроде

with(dt, lapply(split(dt, interaction(location, year)), 
  function(x) sort.int(x$value, partial=2)))

Я сомневаюсь, что это будет быстрее, чем dplyr или data.table, даже если они полностью сортируют с учетом своих оптимизаций, но, возможно, стоило бы посмотреть, если эффективностьбеспокойство.

О, вы также можете сначала отсортировать, а затем сгруппировать и просто выбрать n-е значение из каждой группировки, сохранив несколько процедур сортировки для каждой группы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...