2012-01-17 8 views
9

utilizo ddply resumir algunos data.frame en varias categorías, así:¿Cómo puedo usar ddply con variables variables?

# with both group and size being factors/categorical 
split.df <- ddply(mydata,.(group,size),summarize, 
        sumGroupSize = sum(someValue)) 

Esto funciona sin problemas, pero a menudo me gusta para calcular los coeficientes que implica que tengo que dividir por el total del grupo. ¿Cómo puedo calcular dicho total dentro de la misma llamada ddply?

Digamos que me gustaría tener la cuota de observaciones en el grupo A que están en la clase de tamaño 1. Obviamente, primero tengo que calcular la suma de todas las observaciones en la clase de tamaño 1. Claro que podría hacer esto con dos llamadas ddply, pero usar todas las llamadas sería más cómodo. ¿Hay una manera de hacerlo?

EDIT: No quise preguntar demasiado específico, pero me doy cuenta de que estaba molestando a la gente de aquí. Así que aquí está mi problema específico. De hecho, tengo un ejemplo que funciona, pero no lo considero realmente ingenioso. Además, tiene una falla que debo superar: no funciona correctamente con aplicar.

library(plyr) 

# make the dataset more "realistic" 
mydata <- warpbreaks 
names(mydata) <- c("someValue","group","size") 
mydata$category <- c(1,2,3) 
mydata$categoryA <- c("A","A","X","X","Z","Z") 
# add some NA 
mydata$category[c(8,10,19)] <- NA 
mydata$categoryA[c(14,1,20)] <- NA 


# someValue is summarized ! 
# note we have a another, varying category hence we need the a parameter 
calcShares <- function(a, data) { 
# !is.na needs to be specific! 
tempres1 <- eval(substitute(ddply(data[!is.na(a),],.(group,size,a),summarize, 
       sumTest = sum(someValue,na.rm=T))), 

       envir=data, enclos=parent.frame()) 
tempres2 <- eval(substitute(ddply(data[!is.na(a),],.(group,size),summarize, 
       sumTestTotal = sum(someValue,na.rm=T))), 
       envir=data, enclos=parent.frame()) 

res <- merge(tempres1,tempres2,by=c("group","size")) 
res$share <- res$sumTest/res$sumTestTotal 
return(res) 

} 

test <- calcShares(category,mydata) 
test2 <- calcShares(categoryA,mydata) 
head(test) 
head(test2) 

Como puede ver, tengo la intención de ejecutar esto sobre diferentes variables categóricas. En el ejemplo, tengo solo dos (categoría, categoría A) pero de hecho obtuve más, por lo que usar apply con mi función sería muy agradable, pero de alguna manera no funciona correctamente.

applytest <- head(apply(mydata[grep("^cat", 
      names(mydata),value=T)],2,calcShares,data=mydata)) 

.. devuelve un mensaje de advertencia y un nombre extraño (newX [, i]) para la categoría var.

Entonces, ¿cómo puedo hacer ESTO a) más elegantemente yb) corregir el problema de aplicación?

+0

Nice Q. Siempre lo he hecho con ddply envuelto en otro ddply como usted dijo, por lo que estoy interesado en una solución a esto también. ¿Funcionará 'table' +' prop.table' + 'addmargins' para usted, o necesita la flexibilidad adicional de ddply? –

+0

¿No usarías la función 'count' para eso? Mi memoria es que solo se trata de un cambio de nombre de 'longitud' que se debe usar con 'ave' en la base R. –

+0

Hmm. bueno, no sabía de prop.table, pero todavía podría hacer uso de la flexibilidad de ddply. –

Respuesta

3

Esto parece simple, por lo que me puede estar faltando algún aspecto de su pregunta.

Primero, defina una función que calcule los valores que desea dentro de cada nivel de group. Luego, en lugar de usar .(group, size) para dividir el data.frame, use .(group), y aplique la función recién definida a cada una de las piezas divididas.

library(plyr) 

# Create a dataset with the names in your example 
mydata <- warpbreaks 
names(mydata) <- c("someValue", "group", "size") 

# A function that calculates the proportional contribution of each size class 
# to the sum of someValue within a level of group 
getProps <- function(df) { 
    with(df, ave(someValue, size, FUN=sum)/sum(someValue)) 
} 

# The call to ddply() 
res <- ddply(mydata, .(group), 
      .fun = function(X) transform(X, PROPS=getProps(X))) 

head(res, 12) 
# someValue group size  PROPS 
# 1   26  A L 0.4785203 
# 2   30  A L 0.4785203 
# 3   54  A L 0.4785203 
# 4   25  A L 0.4785203 
# 5   70  A L 0.4785203 
# 6   52  A L 0.4785203 
# 7   51  A L 0.4785203 
# 8   26  A L 0.4785203 
# 9   67  A L 0.4785203 
# 10  18  A M 0.2577566 
# 11  21  A M 0.2577566 
# 12  29  A M 0.2577566 
+0

+1 para traer algunos pensamientos frescos (con/ave/transform) a la mesa. Me di cuenta que era un poco impreciso y publiqué un ejemplo reproducible más específico. Lo que le falta a su solución es el resumen (es decir, la agregación). Pero tal vez pueda agregar esto de alguna manera a su solución. No estoy enfocado en ddply solamente :) –

+0

También me gusta esto, pero no sé si es más simple que solo hacer 2x ddply desde el principio. –

Cuestiones relacionadas