2012-04-16 10 views
19

Me gustaría poder enviar un nombre de columna a una llamada que realizo al ddply. Un ejemplo ddply llamada:Enviar nombre de columna a ddply desde la función

ddply(myData, .(MyGrouping), summarise, count=sum(myColumnName)) 

Si he ddply envuelta dentro de otra función es posible terminar con esto de modo que pueda pasar en un valor arbitrario como myColumnName a la función de llamada?

+0

¿Tiene un ejemplo reproducible (con datos, por ejemplo, utilizando iris)? –

+0

@static_rtti ¿está buscando específicamente una respuesta 'plyr'? Esta pregunta es muy antigua y actualmente hay paquetes mucho más avanzados. –

+0

Bueno, yo uso plyr (y no sé de paquetes más avanzados), pero si puede dar una respuesta al mismo problema con un paquete diferente, también lo encontraría interesante. –

Respuesta

11

Tiene que haber una manera mejor. Y no pude encontrar la manera de hacerlo funcionar con un resumen.

my.fun <- function(df, count.column) { 
    ddply(df, .(x), function(d) sum(d[[count.column]])) 
} 

dat <- data.frame(x=letters[1:2], y=1:10) 

> my.fun(dat, 'y') 
    x V1 
1 a 25 
2 b 30 
> 
+0

Puede pasar el count.column directamente a la función en 'ddply' como en:' ddply (df,. (X), function (d) sum (d [[count.column]])) 'que significa menos código y evitando el 'eval'. –

+0

@TylerRinker Sí, esa evaluación era un vestigio de cuando intentaba hacer que funcione con un resumen. editado – Justin

+0

Intenté esto también (pero ya que realmente no uso mucho plyr) tampoco pude encontrar la manera de hacerlo funcionar con resúmenes. –

7

Esto parece funcionar, aunque probablemente será más limpio (y más seguro) para evitar summarise en esta circunstancia y escribir su propia función anónima como se indica Justin.

yr <- "year" 

summarise(baseball, 
duration = max(eval(parse(text = yr))) - min(eval(parse(text = yr)))) 
4

Como dijo @David Arenburg, esta pregunta es bastante antigua. Hoy, el paquete data.table o dplyr le puede dar el mismo resultado con una velocidad mucho más rápida.

Aquí está la versión data.table de la respuesta.

library(data.table) 
my.fun <- function(myData, MyGrouping, myColumnName) { 
    setDT(myData)[, lapply(.SD, sum), by=MyGrouping, .SDcols=myColumnName] 
} 
0

supongo que encontré una manera que funciona con resumir. No estoy seguro si entiendo por qué, ya que no soy un experto en el tratamiento de los entornos en R, pero aquí está la solución:

> library(plyr) 
> 
> 
> 
> ########################### 
> # Creating test DataFrame # 
> ########################### 
> 
> x <- 1:15 
> 
> set.seed(1) 
> y <- letters[1:3][sample(1:3, 15, replace = T)] 
> 
> df <- data.frame(x, y) 
> 
> ### check df 
> df 
    x y 
1 1 a 
2 2 b 
3 3 b 
4 4 c 
5 5 a 
6 6 c 
7 7 c 
8 8 b 
9 9 b 
10 10 a 
11 11 a 
12 12 a 
13 13 c 
14 14 b 
15 15 c 
> 
> 
> ##################### 
> # auxiliar function # 
> ##################### 
> evalString <- function(s) { 
+ eval(parse(text = s), parent.frame()) 
+ } 
> 
> 
> ### columnName input 
> columnName <- 'x' 
> 
> ### call with columnName as input 
> xMeans <- ddply(df, 
+     'y', 
+     summarise, 
+     mean = mean(evalString(columnName))) 
> 
> 
> ### regular call to ddply 
> xMeans2 <- ddply(df, 
+     'y', 
+     summarise, 
+     mean = mean(x)) 
> 
> 
> ### Compare Results 
> xMeans 
    y mean 
1 a 7.8 
2 b 7.2 
3 c 9.0 
> xMeans2 
    y mean 
1 a 7.8 
2 b 7.2 
3 c 9.0 
> 

EDIT: Puede utilizar la función get del paquete base, como se sugiere aquí: ddply: how do I pass column names as parameters?

> xMeans3 <- ddply(df, 
+     'y', 
+     summarise, 
+     mean = mean(get(columnName))) 
> 
> xMeans3 
    y mean 
1 a 7.8 
2 b 7.2 
3 c 9.0 
Cuestiones relacionadas