2010-11-05 29 views
8

que tienen una trama de datos con 900.000 filas y 11 columnas en R. Los nombres de columna y tipos son los siguientes:subtotales Cálculo de R

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 para calcular los subtotales. Por ejemplo, quiero calcular las sumas en cada cambio en yname, y agregar subtotal a todas las variables numéricas. Hay 160 ynames distintos, por lo que la tabla resultante debería decirme el subtotal de cada yname. Todavía no he ordenado los datos, pero esto no es un problema porque puedo ordenar los datos de la forma que quiera. Debajo hay 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 debo usar aquí? Tal vez algo como SQL group by?

+1

Sería mucho más fácil si nos dio un fragmento de datos o más detalles de lo que realmente quiere. Hay un cierto grado de ironía en su solicitud de ejemplos de nosotros cuando usted no proporciona uno. En serio, es muy probable que la mayoría de los R Gurus no usen Excel y probablemente no lo hayan hecho por mucho tiempo, así que no presumas que sabemos a qué te refieres cuando dices "hazlo como Excel". ¿'Yname' está ordenado? Porque entonces sería una tarea de agregación en R (es decir, desea las sumas del número para los grupos definidos por yname). –

+0

@Gavin Simpson: He actualizado mi pregunta de acuerdo con su comentario. –

+1

aquí hay algunas preguntas relacionadas: http://stackoverflow.com/search?q=%5Br%5D+%22group+by%22 –

Respuesta

10

OK. Suponiendo que sus datos están en un marco de datos denominado foo:

> 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 

Entonces 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. Utilicé la interfaz de fórmula en aggregate(), que es un poco más agradable en este caso porque no necesita todos los bits foo$ en los nombres de variables que desea agregar. Si tiene datos que faltan (NA) en el conjunto de datos completo, entonces usted necesitará añadir un argumento extra na.rm = TRUE la que se van pasando a sum(), así:

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

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) 
4

O el plyr biblioteca, 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 
4

También puede utilizar xtabs o tapply:

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

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

Hay un paquete R llamado sqldf que le permite usar comandos SQL en R data.frames. Además, como ya dijiste, GROUP BY sería agradable. Puede almacenar fácilmente sus datos en una base de datos MySQL local y conectarse a R usando el paquete RMySQL (También puede usar la mayoría de otros DBMS, pero MySQL es el más fácil de configurar).

Por lo que puedo juzgar, plyr es un gran paquete, también. Pero por la forma en que preguntas y comparas tu problema con GROUP BY, supongo que sabes algo sobre SQL, por lo que usarlo podría ser más fácil para ti. Hay funciones cómodas como dbReadTable, además, si sus datos crecen, puede seleccionar solo subpartes de sus datos para que solo ejecute su análisis con lo que realmente necesita.

3

si sus datos son grandes y la velocidad es importante, recomendaría usar la función R rowsum, que es mucho más rápida.Apliqué el 3 métodos (f1 = agregada, f2 = ddply, f3 = tapply) sugirió 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 mi código a continuación si alguien quiere explorar con 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)