2009-11-23 20 views
8

Actualmente utilizo cast en una tabla fundida para calcular el total de cada valor en la combinación de las variables ID1 (nombres de fila) e ID2 (encabezados de columna), junto con totales generales para cada fila usando margins="grand_col".Cálculo del porcentaje del total de la fila con plyr

c <- cast(m, ID1 ~ ID2, sum, margins="grand_col")

ID1  ID2a ID2b  ID2c  ID2d ID2e (all) 
1 ID1a 6459695 885473 648019 453613 1777308 10224108 
2 ID1b 7263529 1411355 587785 612730 2458672 12334071 
3 ID1c 7740364 1253524 682977 886897 3559283 14123045 

Hasta ahora, todo R-similares.

Luego divido cada celda por su fila total para obtener un porcentaje del total.

c[,2:6]<-c[,2:6]/c[,7] 

Esto se ve kludgy. ¿Hay algo que debería hacer en cast o quizás en plyr para manejar el porcentaje de cálculo de margen en el primer comando?

Gracias, Matt

+0

no tengo ningún grandes ideas aquí. ¡Espero que alguien más lo haga! – hadley

Respuesta

4

Asumiendo que su tabla de origen es como la siguiente:

dfm <- structure(list(ID1 = structure(c(1L, 2L, 3L, 1L, 2L, 3L, 1L, 
2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L), .Label = c("ID1a", "ID1b", "ID1c" 
), class = "factor"), ID2 = structure(c(1L, 1L, 1L, 2L, 
2L, 2L, 3L, 3L, 3L, 4L, 4L, 4L, 5L, 5L, 5L), .Label = c("ID2a", 
"ID2b", "ID2c", "ID2d", "ID2e"), class = "factor"), value = c(6459695L, 
7263529L, 7740364L, 885473L, 1411355L, 1253524L, 648019L, 587785L, 
682977L, 453613L, 612730L, 886897L, 1777308L, 2458672L, 3559283L 
)), .Names = c("ID1", "ID2", "value"), row.names = c(NA, 
-15L), class = "data.frame") 

> head(dfm) 
    ID1 ID2 value 
1 ID1a ID2a 6459695 
2 ID1b ID2a 7263529 
3 ID1c ID2a 7740364 
4 ID1a ID2b 885473 
5 ID1b ID2b 1411355 
6 ID1c ID2b 1253524 

Usando ddply primero a calcular los porcentajes y cast para presentar los datos en el formato requerido

library(reshape) 
library(plyr) 

df1 <- ddply(dfm, .(ID1), summarise, ID2 = ID2, pct = value/sum(value)) 
dfc <- cast(df1, ID1 ~ ID2) 

dfc 
    ID1  ID2a  ID2b  ID2c  ID2d  ID2e 
1 ID1a 0.6318101 0.08660638 0.06338147 0.04436700 0.1738350 
2 ID1b 0.5888996 0.11442735 0.04765539 0.04967784 0.1993399 
3 ID1c 0.5480662 0.08875735 0.04835905 0.06279786 0.2520195 

En comparación con su ejemplo, le faltan los totales de la fila, estos deben agregarse sep arately.

No estoy seguro, si esta solución es más elegante que la que tiene actualmente.

+0

Es una solución mejor si solo porque los índices de columna no necesitan estar codificados, y puedo vivir sin los totales de columna. Marcado como la respuesta. Mientras tanto, ¿qué está sucediendo en el argumento ID2 = ID2 en su comando ddply? –

+0

El argumento de resumen de ddply crea un nuevo marco de datos, y si no se especificó ID2, el nuevo marco de datos solo tendría dos columnas: ID1 y pct. – learnr

4

Aquí hay un trazador de líneas usando tapply y prop.table. No se basa en los paquetes auxiliares:

prop.table(tapply(dfm$value, dfm[1:2], sum), 1) 

dando:

 ID2 
ID1   ID2a  ID2b  ID2c  ID2d  ID2e 
    ID1a 0.6318101 0.08660638 0.06338147 0.04436700 0.1738350 
    ID1b 0.5888996 0.11442735 0.04765539 0.04967784 0.1993399 
    ID1c 0.5480662 0.08875735 0.04835905 0.06279786 0.2520195 

o este que es aún más corto:

prop.table(xtabs(value ~., dfm), 1) 
Cuestiones relacionadas