2011-07-12 20 views
12

Estoy escribiendo un informe que requiere la generación de varias tablas dinámicas en Excel. Me gustaría pensar que hay una manera de hacer esto en R para poder evitar Excel. Me gustaría obtener resultados como la captura de pantalla a continuación (nombres de profesores redactados). Hasta donde puedo decir, podría usar el paquete de remodelación para calcular los valores agregados, pero tendría que hacerlo varias veces y de alguna manera obtener todos los datos en el orden correcto. En ese punto, debería estar haciéndolo en Excel. ¿Alguien tiene alguna sugerencia o recomendaciones de paquete? ¡Gracias!Pivote de salida similar a una tabla en R?

(EDIT) Los datos comienzan como una lista de estudiantes, su profesor, escuela y crecimiento. Esta información se agrega para obtener una lista de maestros con el crecimiento promedio de su clase. Tenga en cuenta que los profesores se agrupan por escuela. El mayor problema que preveo al hacer esto con R hasta ahora es ¿cómo se obtienen las filas subtotal y total (BSA1 Total, Gran Total, etc.) allí ya que no son del mismo tipo de observación que las otras? ¿Simplemente tiene que calcularlos manualmente e intentar obtenerlos en el orden correcto para que aparezcan en la parte inferior de ese grupo?

example

+0

La pregunta tal como está ahora es demasiado vaga para ser respondidas razonablemente en el sitio aquí, en mi opinión. Solo puedo decir: aprenda látex si no lo sabe ya, mire esta pregunta: http://stackoverflow.com/questions/5465314/tools-for-making-latex-tables-in-r y obtenga el marco de datos en el formato correcto usando, por ejemplo, 'plyr' o' rehape' o funciones base como 'cast', etc. Obtener el resultado que tiene es bastante fácil en R, pero lo obtendrá en formato de texto. El diseño debe hacerse en otro lugar. –

+0

Debería mirar en R Data Frames. – ATMathew

+1

Sin duda hay varias maneras fáciles de hacerlo en R, pero sería mucho mejor si pudieras proporcionar los datos que comienzan, ya que además del resultado que deseas obtendrás un código mejor y más aplicable. – John

Respuesta

19

Aquí es un botín en los bits de cálculo:

set.seed(1) 
school <- sample(c("BSA1", "BSA2", "HSA1"), 100, replace=T) 
teacher <- sample(c("Tom", "Dick", "Harry"), 100, replace=T) 
growth <- rnorm(100, 5, 3) 

myDf <- data.frame(school, teacher, growth) 

require(reshape2) 

aggregate(growth ~ school + teacher, data =myDf, FUN=mean) 

myDf.melt <- melt(myDf, measured="growth") 
dcast(myDf.melt, school + teacher ~ ., fun.aggregate=mean, margins=c("school", "teacher")) 

yo no he abordado el formato de salida, sólo el cálculo. El marco de datos resultante debe tener el siguiente aspecto:

school teacher  NA 
1 BSA1 Dick 4.663140 
2 BSA1 Harry 4.310802 
3 BSA1  Tom 5.505247 
4 BSA1 (all) 4.670451 
5 BSA2 Dick 6.110988 
6 BSA2 Harry 5.007221 
7 BSA2  Tom 4.337063 
8 BSA2 (all) 5.196018 
9 HSA1 Dick 4.508610 
10 HSA1 Harry 4.890741 
11 HSA1  Tom 4.721124 
12 HSA1 (all) 4.717335 
13 (all) (all) 4.886576 

Ese ejemplo usa el paquete reshape2 para manejar los subtotales.

Creo que R es la herramienta adecuada para el trabajo aquí. Puedo entender totalmente no estar seguro de cómo comenzar con este análisis. Llegué a R desde Excel hace unos años y al principio puede ser difícil asimilar. Permítanme señalar cuatro consejos profesionales para ayudarlo a obtener mejores respuestas en Desbordamiento de pila:

1) proporcionar datos, incluso si son simulados: puede ver que simulé algunos datos al principio de mi respuesta. Si hubiera proporcionado esa simulación, a) me habría ahorrado tiempo b) le habría dado una respuesta que utilizó su propia estructura de datos, no una que yo haya soñado yc) otras personas habrían respondido. A menudo me salteo las preguntas sin datos porque me cansé de adivinar sobre los datos, les dijeron que mi respuesta era una mierda porque adiviné mal.

2) Haga una pregunta clara. "¿Cómo hago mi trabajo?" No es una sola pregunta clara. "¿Cómo puedo tomar este ejemplo de datos y crear subtotales en la agregación como este ejemplo de salida?" Es una pregunta específica única.

3) ¡Sigue preguntando! Todos mejoramos con la práctica. Está tratando de hacer más en R y menos en Excel, por lo que claramente tiene una inteligencia superior a la media. Sigue usando R y sigue haciendo preguntas. Todo será más fácil a tiempo.

4) Tenga cuidado con sus palabras cuando describa las cosas. Usted dice en su pregunta editada que tiene una "lista" de cosas. Una lista en R es una estructura de datos específica. Sospecho que en realidad tienes un marco de datos y estás usando el término "lista" en un sentido genérico. Esto puede generar cierta confusión. También ilustra por qué quieres proporcionar tus propios datos.

+1

¡Gracias! Respuesta extremadamente útil. –

+2

Si tuviera que formatear las direcciones, ¿recomendaría usar xtable y Sweave? ¿O algo más que recomiendas? Gracias de nuevo. –

10

con datos simulados de JD largas, y añadiendo la SD y cuenta:

library(reshape) # not reshape2 
    cast(myDf.melt, school + teacher ~ ., margins=TRUE , c(mean, sd, length)) 
    school teacher  mean  sd length 
1 BSA1 Dick 4.663140 3.718773  14 
2 BSA1 Harry 4.310802 1.430594  9 
3 BSA1  Tom 5.505247 4.045846  4 
4 BSA1 (all) 4.670451 3.095980  27 
5 BSA2 Dick 6.110988 2.304104  15 
6 BSA2 Harry 5.007221 2.908146  9 
7 BSA2  Tom 4.337063 2.789244  14 
8 BSA2 (all) 5.196018 2.682924  38 
9 HSA1 Dick 4.508610 2.946961  11 
10 HSA1 Harry 4.890741 2.977305  13 
11 HSA1  Tom 4.721124 3.193576  11 
12 HSA1 (all) 4.717335 2.950959  35 
13 (all) (all) 4.886576 2.873637 100 
+0

Buena ilustración. Me puse vago y solo lo hice :) –

+0

Pensé que debería ser fácil con dcast :: reshape2 pero no pude hacer que funcionara, así que volví a cast :: reshape. –

+0

oh ... interesante. No puedo hacerlo en reshape2 tampoco. –

1

A continuación se presentan diferentes maneras de generar este utilizando el relativamente nuevo paquete pivottabler.

Divulgación: soy el autor del paquete.

Para obtener más información, consulte la página del paquete en CRAN y las diversas viñetas de paquetes disponibles en esa página.

datos de muestra (igual al anterior)

set.seed(1) 
school <- sample(c("BSA1", "BSA2", "HSA1"), 100, replace=T) 
teacher <- sample(c("Tom", "Dick", "Harry"), 100, replace=T) 
growth <- rnorm(100, 5, 3) 
myDf <- data.frame(school, teacher, growth) 

resultados de tablas pivote rápido a consola como texto sin formato salida

library(pivottabler) 
# arguments: qhpvt(dataFrame, rows, columns, calculations, ...) 
qpvt(myDf, c("school", "teacher"), NULL, 
    c("Average Growth"="mean(growth)", "Std Dev"="sd(growth)", 
     "# of Scholars"="n()"), 
    formats=list("%.1f", "%.1f", "%.0f")) 

Console:

   Average Growth Std Dev # of Scholars 
BSA1 Dick    4.7  3.7    14 
     Harry    4.3  1.4    9 
     Tom    5.5  4.0    4 
     Total    4.7  3.1    27 
BSA2 Dick    6.1  2.3    15 
     Harry    5.0  2.9    9 
     Tom    4.3  2.8    14 
     Total    5.2  2.7    38 
HSA1 Dick    4.5  2.9    11 
     Harry    4.9  3.0    13 
     Tom    4.7  3.2    11 
     Total    4.7  3.0    35 
Total     4.9  2.9   100 

resultados de tablas pivote rápida como un widget html

library(pivottabler) 
qhpvt(myDf, c("school", "teacher"), NULL, 
    c("Average Growth"="mean(growth)", "Std Dev"="sd(growth)", 
     "# of Scholars"="n()"), 
    formats=list("%.1f", "%.1f", "%.0f")) 

HTML Widget de salida: tabla pivote

enter image description here

generando usando sintaxis más detallado

Esto tiene más opciones, por ejemplo, cambio de nombre de totales

library(pivottabler) 
pt <- PivotTable$new() 
pt$addData(myDf) 
pt$addRowDataGroups("school", totalCaption="(all)") 
pt$addRowDataGroups("teacher", totalCaption="(all)") 
pt$defineCalculation(calculationName="c1", caption="Average Growth", 
    summariseExpression="mean(growth)", format="%.1f") 
pt$defineCalculation(calculationName="c2", caption="Std Dev", 
    summariseExpression="sd(growth)", format="%.1f") 
pt$defineCalculation(calculationName="c3", caption="# of Scholars", 
    summariseExpression="n()", format="%.0f") 
pt # to output to console as plain text 
pt$renderPivot() # to output as a html widget 

HTML Widget de salida:

enter image description here

0

Lo siento por autopromoción, pero echa un vistazo a mi paquete expss.

Código

para generar de salida a continuación:

set.seed(1) 
school <- sample(c("BSA1", "BSA2", "HSA1"), 100, replace=T) 
teacher <- sample(c("Tom", "Dick", "Harry"), 100, replace=T) 
growth <- rnorm(100, 5, 3) 

myDf <- data.frame(school, teacher, growth) 

library(expss) 
myDf %>% 
    # 'tab_cells' - variables on which statistics will be calculated 
    # "|" is needed to suppress 'growth' in row labels 
    tab_cells("|" = growth) %>% 
    # 'tab_cols' - variables for columns. Can be ommited 
    tab_cols(total(label = "")) %>% 
    # 'tab_rows' - variables for rows. 
    tab_rows(school %nest% list(teacher, "(All)"), "|" = "(All)") %>% 
    # 'method = list' is needed for statistics labels in column 
    tab_stat_fun("Average Growth" = mean, 
       "Std Dev" = sd, 
       "# of scholars" = length, 
       method = list) %>% 
    # finalize table 
    tab_pivot() 

Código anterior muestra objeto heredado de data.frame que se puede utilizar con operaciones estándar R (subconjuntos con [ y etc.). Pero hay un método especial print para este objeto. salida de la consola:

|  |  | Average Growth | Std Dev | # of scholars | 
| ----- | ----- | -------------- | ------- | ------------- | 
| BSA1 | Dick |   4.7 |  3.7 |   14 | 
|  | Harry |   4.3 |  1.4 |    9 | 
|  | Tom |   5.5 |  4.0 |    4 | 
|  | (All) |   4.7 |  3.1 |   27 | 
| BSA2 | Dick |   6.1 |  2.3 |   15 | 
|  | Harry |   5.0 |  2.9 |    9 | 
|  | Tom |   4.3 |  2.8 |   14 | 
|  | (All) |   5.2 |  2.7 |   38 | 
| HSA1 | Dick |   4.5 |  2.9 |   11 | 
|  | Harry |   4.9 |  3.0 |   13 | 
|  | Tom |   4.7 |  3.2 |   11 | 
|  | (All) |   4.7 |  3.0 |   35 | 
| (All) |  |   4.9 |  2.9 |   100 | 

Salida a través de htmlTable en knitr, visor rstudio o brillante: