Trabajar con un marco de datos similar a este:
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
Estoy tratando de agregar una columna con numeración dentro de cada grupo. Hacerlo de esta manera obviamente no está usando los poderes 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
¿Cuál sería una buena manera de hacer esto?

Respuestas:
Uso
ave,ddply,dplyrodata.table:o:
o:
o (la memoria más eficiente, ya que se asigna por referencia dentro
DT):fuente
aveda un flotador en lugar de un int aquí. Alternativamente, podría cambiardf$valaseq_len(nrow(df)). Me encontré con esto por aquí: stackoverflow.com/questions/42796857/…data.tablesolución parece ser más rápida que usarfrank:library(microbenchmark); microbenchmark(a = DT[, .(val ,num = frank(val)), by = list(cat)] ,b =DT[, .(val , id = seq_len(.N)), by = list(cat)] , times = 1000L)dplyrsolucion es buena. Pero si, como yo, seguiste recibiendo errores extraños al probar este enfoque, asegúrate de no tener conflictosplyry,dplyrcomo se explica en esta publicación , se puede evitar llamando explícitamentedplyr::mutate(...)data.tablemétodo essetDT(df)[, id:=rleid(val), by=.(cat)]library(plyr)ylibrary(dplyr)responder para hacer la columna val de clasificación en orden descendente?Por hacer esto r-faqpregunta más completa, una alternativa base R con
sequenceyrle:que da el resultado deseado:
Si
df$cates una variable de factor,as.characterprimero debe envolverla :fuente
catcolumna para ser ordenado?catAquí hay una opción que usa un
forbucle por grupos en lugar de por filas (como lo hizo OP)fuente
Aquí hay un pequeño truco de mejora que permite ordenar 'val' dentro de los grupos:
fuente
Me gustaría agregar una
data.tablevariante usando larank()función que proporciona la posibilidad adicional de cambiar el orden y, por lo tanto, la hace un poco más flexible que laseq_len()solución y es bastante similar a las funciones row_number en RDBMS.fuente
Otra
dplyrposibilidad podría ser:fuente
1:n()usarseq_len(n())es más seguro, en el caso de que en su secuencia de operaciones tenga una situación en la quen()podría regresar0, porque1:0le da un vector de longitud dos mientras queseq_len(0)da un vector de longitud cero, evitando así un error de desajuste de longitud conmutate().Usando la
rowid()función endata.table:fuente