forma más rápida de crear una variable que agregue una columna por id

¿Hay una manera más rápida de hacer esto? Supongo que esto es innecesario y que una tarea como esta se puede realizar con funciones básicas.

df <- ddply(df, "id", function(x) cbind(x, perc.total = sum(x$cand.perc))) 

Soy bastante nuevo en R. Miré by() , aggregate() y tapply() , pero no conseguí que funcionasen en absoluto o de la manera que quería. En lugar de devolver un vector más corto, quiero adjuntar la sum al dataframe original. ¿Cuál es la mejor manera de hacer esto?

Editar: Aquí hay una comparación de velocidad de las respuestas aplicadas a mis datos.

 > # My original solution > system.time( ddply(df, "id", function(x) cbind(x, perc.total = sum(x$cand.perc))) ) user system elapsed 14.405 0.000 14.479 > # Paul Hiemstra > system.time( ddply(df, "id", transform, perc.total = sum(cand.perc)) ) user system elapsed 15.973 0.000 15.992 > # Richie Cotton > system.time( with(df, tapply(df$cand.perc, df$id, sum))[df$id] ) user system elapsed 0.048 0.000 0.048 > # John > system.time( with(df, ave(cand.perc, id, FUN = sum)) ) user system elapsed 0.032 0.000 0.030 > # Christoph_J > system.time( df[ , list(perc.total = sum(cand.perc)), by="id"][df]) user system elapsed 0.028 0.000 0.028 

Para cualquier tipo de agregación en la que desee un vector resultante de la misma longitud que el vector de entrada con réplicas agrupadas en el vector de agrupación ave es lo que desea.

 df$perc.total <- ave(df$cand.perc, df$id, FUN = sum) 

Ya que eres bastante nuevo en R y la velocidad es aparentemente un problema para ti, recomiendo el paquete data.table , que es realmente rápido. Una forma de resolver su problema en una línea es la siguiente:

 library(data.table) DT <- data.table(ID = rep(c(1:3), each=3), cand.perc = 1:9, key="ID") DT <- DT[ , perc.total := sum(cand.perc), by = ID] DT ID Perc.total cand.perc [1,] 1 6 1 [2,] 1 6 2 [3,] 1 6 3 [4,] 2 15 4 [5,] 2 15 5 [6,] 2 15 6 [7,] 3 24 7 [8,] 3 24 8 [9,] 3 24 9 

Descargo de responsabilidad: no soy un experto en data.table (yet ;-), por lo que podría haber formas más rápidas de hacerlo. Consulte el sitio del paquete para comenzar si está interesado en usar el paquete: http://datatable.r-forge.r-project.org/

Use tapply para obtener las estadísticas del grupo, luego agréguelas nuevamente a su conjunto de datos.

Ejemplo reproducible:

 means_by_wool <- with(warpbreaks, tapply(breaks, wool, mean)) warpbreaks$means.by.wool <- means_by_wool[warpbreaks$wool] 

Solución no probada para su escenario:

 sum_by_id <- with(df, tapply(cand.perc, id, sum)) df$perc.total <- sum_by_id[df$id] 

ilprincipe si ninguno de los anteriores se ajusta a sus necesidades, podría intentar transponer sus datos

 dft=t(df) 

luego usa aggregate

 dfta=aggregate(dft,by=list(rownames(dft)),FUN=sum) 

A continuación tienes tus nombres

 rownames(dfta)=dfta[,1] dfta=dfta[,2:ncol(dfta)] 

Transponer a la orientación original

 df2=t(dfta) 

y se unen a los datos originales

 newdf=cbind(df,df2) 

¿Por qué está utilizando cbind (x, …) la salida de ddply se agregará automáticamente. Esto debería funcionar:

 ddply(df, "id", transform, perc.total = sum(cand.perc)) 

deshacerse de las cosas superfluas debería acelerar las cosas.

También puede cargar su backend foreach favorito y probar el argumento .parallel = TRUE para ddply.