Как суммировать 3 верхних значения в наборе данных при наличии связей - PullRequest
3 голосов
/ 11 мая 2019

У меня есть фрейм данных (my_data), и я хочу вычислить сумму только 3 самых высоких значений, даже если могут быть связи.Я довольно новичок в R, и я использовал dplyr.

A tibble: 15 x 3
   city      month number
   <chr>     <chr>  <dbl>
 1 Lund      jan       12
 2 Lund      feb       12
 3 Lund      mar       18
 4 Lund      apr       28
 5 Lund      may       28
 6 Stockholm jan       15
 7 Stockholm feb       15
 8 Stockholm mar       30
 9 Stockholm apr       30
10 Stockholm may       10
11 Uppsala   jan       22
12 Uppsala   feb       30
13 Uppsala   mar       40
14 Uppsala   apr       60
15 Uppsala   may       30

Это код, который я пробовал:

# For each city, count the top 3 of variable number
my_data %>% group_by(city) %>% top_n(3, number) %>% summarise(top_nr = sum(number))

Ожидаемый (требуемый) вывод:

# A tibble: 3 x 2
  city      top_nr
  <chr>      <dbl>
1 Lund          86
2 Stockholm     75
3 Uppsala      130

, но фактический выход R равен:

# A tibble: 3 x 2
  city      top_nr
  <chr>      <dbl>
1 Lund          86
2 Stockholm     90
3 Uppsala      160

Похоже, что при наличии связей все связанные значения включаются в сумму.Я хотел, чтобы были подсчитаны только 3 уникальных экземпляра с самыми высокими значениями.

Любая помощь будет принята с благодарностью!:)

Ответы [ 4 ]

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

Мы можем сделать distinct, чтобы удалить дубликаты элементов. Способ, которым работает top_n, заключается в том, что, если значения дублируются, он сохранит столько строк дублирования

my_data %>% 
   distinct(city, number, .keep_all = TRUE) %>%
   group_by(city) %>%
   top_n(3, number) %>%
   summarise(top_nr = sum(number))

Обновление

На основе нового выхода OP, после вывода top_n (который не является arrange d), расположите «число» в порядке убывания и получите sum из первых 3 «чисел»

my_data %>% 
   group_by(city) %>% 
   top_n(3, number) %>% 
   arrange(city,  desc(number)) %>% 
   summarise(number = sum(head(number, 3)))
# A tibble: 3 x 2
#  city      number
#  <chr>      <int>
#1 Lund          74
#2 Stockholm     75
#3 Uppsala      130

Данные

my_data <- structure(list(city = c("Lund", "Lund", "Lund", "Lund", "Lund", 
"Stockholm", "Stockholm", "Stockholm", "Stockholm", "Stockholm", 
"Uppsala", "Uppsala", "Uppsala", "Uppsala", "Uppsala"), month = c("jan", 
"feb", "mar", "apr", "may", "jan", "feb", "mar", "apr", "may", 
"jan", "feb", "mar", "apr", "may"), number = c(12L, 12L, 18L, 
28L, 28L, 15L, 15L, 30L, 30L, 10L, 22L, 30L, 40L, 60L, 30L)), 
class = "data.frame", row.names = c("1", 
"2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", 
"14", "15"))
2 голосов
/ 11 мая 2019

Жизнь может быть намного проще без top_n():

dat %>%
  group_by(city) %>%
  summarize(
    top_nr = sum(tail(sort(number), 3))
    )
2 голосов
/ 11 мая 2019

Это tidyverse (на самом деле, dplyr) решение почти равно akrun's , но filter s в кадре данных вместо получения top_n.

library(tidyverse)

my_data %>%
  group_by(city) %>%
  arrange(desc(number), .by_group = TRUE) %>%
  filter(row_number() %in% 1:3) %>%
  summarise(top_nr = sum(number))
## A tibble: 3 x 2
#  city      top_nr
#  <chr>      <int>
#1 Lund          74
#2 Stockholm     75
#3 Uppsala      130
1 голос
/ 11 мая 2019

Спасибо @akrun, но когда я запускаю предложенный вами код, я получаю: для Лунда 58, который является сводкой 28, 18 и 12. То, что я хотел, было способом суммировать для Лунда 28 + 28 + 18 = 74. (Я вижу, что я сделал ошибку выше в моем первоначальном описании, извините за это). Вот как должен выглядеть ожидаемый (желаемый) результат:

# A tibble: 3 x 2
  city      top_nr
  <chr>      <dbl>
1 Lund          74
2 Stockholm     75
3 Uppsala      130
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...