Travailler avec un bloc de données similaire à celui-ci:
set.seed(100)
df <- data.frame(cat = c(rep("aaa", 5), rep("bbb", 5), rep("ccc", 5)), val = runif(15))
df <- df[order(df$cat, df$val), ]
df
cat val
1 aaa 0.05638315
2 aaa 0.25767250
3 aaa 0.30776611
4 aaa 0.46854928
5 aaa 0.55232243
6 bbb 0.17026205
7 bbb 0.37032054
8 bbb 0.48377074
9 bbb 0.54655860
10 bbb 0.81240262
11 ccc 0.28035384
12 ccc 0.39848790
13 ccc 0.62499648
14 ccc 0.76255108
15 ccc 0.88216552
J'essaye d'ajouter une colonne avec la numérotation dans chaque groupe. Faire de cette façon n'utilise évidemment pas les pouvoirs de R:
df$num <- 1
for (i in 2:(length(df[,1]))) {
if (df[i,"cat"]==df[(i-1),"cat"]) {
df[i,"num"]<-df[i-1,"num"]+1
}
}
df
cat val num
1 aaa 0.05638315 1
2 aaa 0.25767250 2
3 aaa 0.30776611 3
4 aaa 0.46854928 4
5 aaa 0.55232243 5
6 bbb 0.17026205 1
7 bbb 0.37032054 2
8 bbb 0.48377074 3
9 bbb 0.54655860 4
10 bbb 0.81240262 5
11 ccc 0.28035384 1
12 ccc 0.39848790 2
13 ccc 0.62499648 3
14 ccc 0.76255108 4
15 ccc 0.88216552 5
Quelle serait une bonne façon de faire cela?
Réponses:
Utilisez
ave
,ddply
,dplyr
oudata.table
:ou:
ou:
ou (le plus efficace en mémoire, comme il l'attribue par référence dans
DT
):la source
ave
donne ici un float au lieu d'un int. Alternativement, pourrait changerdf$val
enseq_len(nrow(df))
. Je viens de rencontrer ceci ici: stackoverflow.com/questions/42796857/…data.table
solution semble être plus rapide que d'utiliserfrank
:library(microbenchmark); microbenchmark(a = DT[, .(val ,num = frank(val)), by = list(cat)] ,b =DT[, .(val , id = seq_len(.N)), by = list(cat)] , times = 1000L)
dplyr
solution est bonne. Mais si, comme moi, vous continuiez à avoir des erreurs étranges en essayant cette approche, assurez-vous que vousplyr
dplyr
dplyr::mutate(...)
data.table
méthode estsetDT(df)[, id:=rleid(val), by=.(cat)]
library(plyr)
etlibrary(dplyr)
réponses pour rendre la colonne de classement val par ordre décroissant?Pour faire cela r-faqquestion plus complète, une alternative de base R avec
sequence
etrle
:ce qui donne le résultat attendu:
S'il
df$cat
s'agit d'une variable de facteur, vous devez d'abord l'envelopperas.character
:la source
cat
le tri des colonnes?cat
Voici une option utilisant une
for
boucle par groupes plutôt que par lignes (comme OP l'a fait)la source
Voici une petite astuce d'amélioration qui permet de trier 'val' à l'intérieur des groupes:
la source
Je voudrais ajouter une
data.table
variante en utilisant larank()
fonction qui offre la possibilité supplémentaire de modifier la commande et la rend donc un peu plus flexible que laseq_len()
solution et est assez similaire aux fonctions row_number dans SGBDR.la source
Une autre
dplyr
possibilité pourrait être:la source
1:n()
utiliserseq_len(n())
est plus sûr, dans le cas où dans votre séquence d'opérations vous avez une situation oùn()
pourrait revenir0
, car1:0
vous donne un vecteur de longueur deux tandis queseq_len(0)
donne un vecteur de longueur zéro, évitant ainsi une erreur de discordance de longueur avecmutate()
.Utilisation de la
rowid()
fonction dansdata.table
:la source