3
votes

Comment résumer les 3 valeurs les plus élevées d'un jeu de données en cas d'égalité

J'ai un bloc de données (mes_données) et je souhaite calculer la somme des 3 valeurs les plus élevées uniquement, même s'il peut y avoir des liens. Je suis assez nouveau dans R et j'ai utilisé dplyr .

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

Voici le code que j'ai essayé:

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

Le résultat attendu (voulu) est:

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

mais la sortie réelle de R est:

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

Il semble que s'il y a des égalités, toutes les valeurs liées sont incluses dans la sommation. Je voulais seulement compter 3 instances uniques avec les valeurs les plus élevées.

Toute aide serait très appréciée! :)


3 commentaires

Votre exemple et les numéros de sortie affichés semblent être différents. Est-ce sur un ensemble de données différent


Veuillez utiliser dput pour fournir vos données afin qu'il soit plus facile de reproduire le problème.


@NelsonGon Je ne connaissais pas la fonction dput. Je vais l'utiliser à l'avenir.


4 Réponses :


4
votes

Nous pouvons faire un distinct pour supprimer les éléments en double. Le fonctionnement de top_n est que si les valeurs sont dupliquées, il conservera autant de lignes de dupe

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"))

Update

En fonction de la La nouvelle sortie d'OP, après la sortie top_n (qui n'est pas arrange d), récupère le 'nombre' par ordre décroissant et obtient la somme sur les 3 premiers "nombre"

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

données

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


5 commentaires

Merci @akrun mais quand j'exécute votre code suggéré, je reçois


Pourquoi utiliser head ici? J'ai essayé quelque chose de similaire et j'ai obtenu des résultats étranges.


@NelsonGon Sur la base de la nouvelle sortie, l'OP n'élimine pas les dupes, mais ne prend que les 3 premiers, top_n donne autant de lignes qu'il y a de dupes


Ah, je vois. Merci pour l'explication.


@akrun belle solution! Merci!



1
votes

Merci @akrun mais quand j'exécute votre code suggéré, j'obtiens: pour Lund 58 qui est un résumé de 28, 18 et 12. Ce que je voulais, c'était un moyen de résumer pour Lund 28 + 28 + 18 = 74. (Je vois que j'ai fait une erreur ci-dessus dans ma description initiale, désolé pour cela). Voici à quoi devrait ressembler le résultat attendu (souhaité):

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


0 commentaires

2
votes

Cette solution tidyverse (en fait, dplyr ) est presque égale à akrun , mais filtre est le dataframe à la place d'obtenir le 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


0 commentaires

3
votes

La vie pourrait être bien plus simple sans top_n():

dat %>%
  group_by(city) %>%
  summarize(
    top_nr = sum(tail(sort(number), 3))
    )


3 commentaires

Hou la la! Très succinct! Mais en tant que R-amateur, je trouve la partie: sum (tail (sort (number), 3)), assez difficile à comprendre (même si cela réglait vraiment le problème).


En partant du milieu, il tri le numéro dans ordre croissant ; après cela, tail renvoie les 3 derniers nombres du résultat précédent, et passe ces nombres dans la fonction sum , qui les additionne.


Agréable! Merci! :)