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!
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
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
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
où order
est fourni à la fois les valeurs primaire et décisive pour chaque groupe.
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