Pregunta

Tengo una trama de datos con 900.000 filas y 11 columnas en nombres y tipos de columna R. Los son los siguientes:

column name: date / mcode / mname / ycode / yname / yissue  / bsent   / breturn / tsent   / treturn / csales
type:        Date / Char  / Char  / Char  / Char  / Numeric / Numeric / Numeric / Numeric / Numeric / Numeric

Quiero calcular los subtotales. Por ejemplo, quiero calcular las sumas en cada cambio de yname, y añadir subtotal a todas las variables numéricas. Hay 160 ynames distintas, por lo que la tabla resultante me diga el subtotal de cada yname. No he ordenado los datos todavía, pero esto no es un problema porque puedo ordenar los datos en la forma que yo quiero. A continuación se muestra un fragmento de mis datos:

             date     mcode mname            ycode    yname   yissue bsent breturn tsent treturn csales
417572 2010-07-28     45740 ENDPOINT A        5772    XMAG  20100800     7       0     7       0      0
417573 2010-07-31     45740 ENDPOINT A        5772    XMAG  20100800     0       0     0       0      1
417574 2010-08-04     45740 ENDPOINT A        5772    XMAG  20100800     0       0     0       0      1
417575 2010-08-14     45740 ENDPOINT A        5772    XMAG  20100800     0       0     0       0      1
417576 2010-08-26     45740 ENDPOINT A        5772    XMAG  20100800     0       4     0       0      0
417577 2010-07-28     45741 ENDPOINT L        5772    XMAG  20100800     2       0     2       0      0
417578 2010-08-04     45741 ENDPOINT L        5772    XMAG  20100800     2       0     2       0      0
417579 2010-08-26     45741 ENDPOINT L        5772    XMAG  20100800     0       4     0       0      0
417580 2010-07-28     46390 ENDPOINT R        5772    XMAG  20100800     3       0     3       0      1
417581 2010-07-29     46390 ENDPOINT R        5772    XMAG  20100800     0       0     0       0      2
417582 2010-08-01     46390 ENDPOINT R        5779    YMAG  20100800     3       0     3       0      0
417583 2010-08-11     46390 ENDPOINT R        5779    YMAG  20100800     0       0     0       0      1
417584 2010-08-20     46390 ENDPOINT R        5779    YMAG  20100800     0       0     0       0      1
417585 2010-08-24     46390 ENDPOINT R        5779    YMAG  20100800     2       0     2       0      1
417586 2010-08-26     46390 ENDPOINT R        5779    YMAG  20100800     0       2     0       2      0
417587 2010-07-28     46411 ENDPOINT D        5779    YMAG  20100800     6       0     6       0      0
417588 2010-08-08     46411 ENDPOINT D        5779    YMAG  20100800     0       0     0       0      1
417589 2010-08-11     46411 ENDPOINT D        5779    YMAG  20100800     0       0     0       0      1
417590 2010-08-26     46411 ENDPOINT D        5779    YMAG  20100800     0       4     0       4      0

¿Qué función debería usar aquí? Tal vez algo como group by SQL?

¿Fue útil?

Solución

OK. Suponiendo que sus datos están en una trama de datos foo llamado:

> head(foo)
             date mcode      mname ycode yname   yissue bsent breturn tsent
417572 2010/07/28 45740 ENDPOINT A  5772  XMAG 20100800     7       0     7
417573 2010/07/31 45740 ENDPOINT A  5772  XMAG 20100800     0       0     0
417574 2010/08/04 45740 ENDPOINT A  5772  XMAG 20100800     0       0     0
417575 2010/08/14 45740 ENDPOINT A  5772  XMAG 20100800     0       0     0
417576 2010/08/26 45740 ENDPOINT A  5772  XMAG 20100800     0       4     0
417577 2010/07/28 45741 ENDPOINT L  5772  XMAG 20100800     2       0     2
       treturn csales
417572       0      0
417573       0      1
417574       0      1
417575       0      1
417576       0      0
417577       0      0

A continuación, esto va a hacer la agregación de las columnas numéricas en sus datos:

> aggregate(cbind(bsent, breturn, tsent, treturn, csales) ~ yname, data = foo, 
+           FUN = sum)
  yname bsent breturn tsent treturn csales
1  XMAG    14       8    14       0      6
2  YMAG    11       6    11       6      5

que estaba utilizando el fragmento de datos que incluyó en su P. utiliza la interfaz fórmula para aggregate(), que es un poco más agradable en este caso debido a que no es necesario que todos los bits foo$ sobre los nombres de las variables que desea el agregado . Si le faltan datos (NA) en el conjunto de datos completo, entonces tendrá que añadir una na.rm = TRUE argumento adicional que se van pasando a sum(), así:

> aggregate(cbind(bsent, breturn, tsent, treturn, csales) ~ yname, data = foo, 
+           FUN = sum, na.rm = TRUE)

Otros consejos

O la biblioteca plyr, que es fácilmente extensible a otras clases de datos:

> library(plyr)
> result.2 <- ddply(df$a, .(df$b), sum)
> result.2
  df.b V1
1 down 30
2   up 25

También puede utilizar xtabs o tapply:

xtabs(cbind(bsent, breturn, tsent, treturn, csales) ~ yname, data)

tapply(data$bsent, data$yname, sum)

Si los datos son asuntos grandes y velocidad, yo recomendaría usar el rowsum función de R, que es mucho más rápido. apliqué los 3 métodos (f1 = agregada, f2 = ddply, f3 = tapply) sugeridos en las respuestas al compararlo con f4 = rowsum y esto es lo que parece:

   test replications elapsed relative
4 f4()          100   0.033     1.00
3 f3()          100   0.046     1.39
1 f1()          100   0.165     5.00
2 f2()          100   0.605    18.33

He añadido el código a continuación si alguien quiere explorar en más detalle.

library(plyr);
library(rbenchmark);

val  = rnorm(50);
name = rep(letters[1:5], each = 10);
data = data.frame(val, name);

f1 = function(){aggregate(data$val, by=list(data$name), FUN=sum)}
f2 = function(){ddply(data, .(name), summarise, sum = sum(val))}
f3 = function(){tapply(data$val, data$name, sum)}
f4 = function(){rowsum(x = data$val, group = data$name)}

benchmark(f1(), f2(), f3(), f4(),
          columns=c("test", "replications", "elapsed", "relative"),
          order="relative", replications=100)

Se puede utilizar aggregate

Por ejemplo, supongamos que usted tiene

val = rnorm(50)
name = rep(letters[1:5], each=10)
data <- data.frame(val, name)

A continuación, puede hacer

aggregate(data$val, by=list(data$name), FUN=sum)

Hay un paquete de R sqldf llamada que le permite utilizar comandos SQL en data.frames R. Además, como ya se ha dicho, GROUP BY estaría bien. Se pueden almacenar los datos en una base de datos MySQL local y conecta a R utilizando el paquete RMySQL (se puede utilizar la mayoría de otros DBMS también, pero MySQL es el más fácil de configurar).

Por lo que yo puedo juzgar que plyr es un gran paquete, también. Pero a partir de la forma de preguntar y comparar su problema a GROUP BY, supongo que sabes algo acerca de SQL, por lo que usar esto podría ser más fácil para usted. Hay cómodas funciones como dbReadTable, además de si sus datos se hace más grande sólo puede seleccionar subpartes de sus datos a solamente ejecutar su análisis con lo que realmente necesita.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top