web-dev-qa-db-fra.com

Comment se classer au sein des groupes dans R?

OK, consultez ce cadre de données ...

  customer_name order_dates order_values
1          John  2010-11-01           15
2           Bob  2008-03-25           12
3          Alex  2009-11-15            5
4          John  2012-08-06           15
5          John  2015-05-07           20

Disons que je veux ajouter une variable de commande qui classe la valeur de la commande la plus élevée, par nom, par date de commande maximale, en utilisant la date de la dernière commande au niveau du départage. Donc, finalement, les données devraient ressembler à ceci:

  customer_name order_dates order_values ranked_order_values_by_max_value_date
1          John  2010-11-01           15                               3
2           Bob  2008-03-25           12                               1
3          Alex  2009-11-15            5                               1
4          John  2012-08-06           15                               2
5          John  2015-05-07           20                               1

Lorsque la commande unique de chaque personne obtient 1, et que toutes les commandes suivantes sont classées en fonction de la valeur, et que le bris d'égalité correspond à la date de la dernière commande ayant la priorité. Dans cet exemple, l'ordre de John du 8/6/2012 obtient le rang n ° 2 parce qu'il a été placé après le 11/1/2010. La commande du 5/7/2015 est 1 parce que c'était la plus grosse. Ainsi, même si cette commande a été passée il y a 20 ans, il devrait s'agir du rang n ° 1, car il s'agissait de la plus haute valeur de commande de John.

Est-ce que quelqu'un sait comment je peux faire cela dans R? Où puis-je classer dans un groupe de variables spécifiées dans un bloc de données?

Merci de votre aide!

7
Saul Feliz

Vous pouvez le faire assez proprement avec dplyr

library(dplyr)
df %>%
    group_by(customer_name) %>%
    mutate(my_ranks = order(order(order_values, order_dates, decreasing=TRUE)))

Source: local data frame [5 x 4]
Groups: customer_name

  customer_name order_dates order_values my_ranks
1          John  2010-11-01           15        3
2           Bob  2008-03-25           12        1
3          Alex  2009-11-15            5        1
4          John  2012-08-06           15        2
5          John  2015-05-07           20        1
7
cdeterman

La réponse la mieux notée (par cdeterman) est en fait incorrecte. La fonction d'ordre indique l'emplacement des valeurs classées 1, 2, 3, etc., et non les rangs des valeurs dans leur ordre actuel.

Prenons un exemple simple où nous voulons classer, en commençant par le plus grand, en regroupant par nom de client. J'ai inclus un classement manuel afin que nous puissions vérifier les valeurs

    > df
       customer_name order_values manual_rank
    1           John            2           5
    2           John            5           2
    3           John            9           1
    4           John            1           6
    5           John            4           3
    6           John            3           4
    7           Lucy            4           4
    8           Lucy            9           1
    9           Lucy            6           3
    10          Lucy            2           6
    11          Lucy            8           2
    12          Lucy            3           5

Si je lance le code suggéré par cdeterman j'obtiens les rangs incorrects suivants:

    > df %>%
    +   group_by(customer_name) %>%
    +   mutate(my_ranks = order(order_values, decreasing=TRUE))
    Source: local data frame [12 x 4]
    Groups: customer_name [2]

       customer_name order_values manual_rank my_ranks
              <fctr>        <dbl>       <dbl>    <int>
    1           John            2           5        3
    2           John            5           2        2
    3           John            9           1        5
    4           John            1           6        6
    5           John            4           3        1
    6           John            3           4        4
    7           Lucy            4           4        2
    8           Lucy            9           1        5
    9           Lucy            6           3        3
    10          Lucy            2           6        1
    11          Lucy            8           2        6
    12          Lucy            3           5        4

Ordre est utilisé pour réordonner dataframes en diminuant ou en ordre croissant. Ce que nous voulons réellement, c’est exécuter deux fois la fonction de commande, la fonction de second ordre nous donnant les rangs réels que nous voulons.

    > df %>%
    +   group_by(customer_name) %>%
    +   mutate(good_ranks = order(order(order_values, decreasing=TRUE)))
    Source: local data frame [12 x 4]
    Groups: customer_name [2]

       customer_name order_values manual_rank good_ranks
              <fctr>        <dbl>       <dbl>      <int>
    1           John            2           5          5
    2           John            5           2          2
    3           John            9           1          1
    4           John            1           6          6
    5           John            4           3          3
    6           John            3           4          4
    7           Lucy            4           4          4
    8           Lucy            9           1          1
    9           Lucy            6           3          3
    10          Lucy            2           6          6
    11          Lucy            8           2          2
    12          Lucy            3           5          5
12
T. Himmel

En base R, vous pouvez le faire avec le logiciel légèrement lourd

transform(df,rank=ave(1:nrow(df),customer_name,
  FUN=function(x) order(order_values[x],order_dates[x],decreasing=TRUE)))
 customer_name order_dates order_values ​​rank 
 1 John 2010-11-01 15 3 
 2 Bob 2008-03-25 12 1 
 3 Alex 2009-11-15 5 1 
 4 John 2012-08-06 15 2 
 5 John 2015-05-07 20 1 

order est fourni à la fois les valeurs primaire et décisive pour chaque groupe.

2
A. Webb

Ceci peut être réalisé avec ave et rank. ave passe les groupes appropriés à rank. Le résultat de rank est inversé en raison de l'ordre demandé:

with(x, ave(as.numeric(order_dates), customer_name, FUN=function(x) rev(rank(x))))
## [1] 3 1 1 2 1
1
Matthew Lundberg