2010-07-15 5 views
7

Me gustaría usar el paquete data.table en R para generar agregaciones dinámicamente, pero me está dando un error. A continuación, deje que my.dt sea del tipo data.table.data.table y "por debe evaluar a la lista" Error

sex <- c("M","F","M","F") 
age <- c(19, 23, 26, 21) 
dependent.variable <- c(1400, 1500, 1250, 1100) 
my.dt <- data.table(sex, age, dependent.variable) 
grouping.vars <- c("sex", "age") 
for (i in 1:2) { 
    my.dt[,sum(dependent.variable), by=grouping.vars[i]] 
} 

Si funciono esto, tengo errores:

Error in `[.data.table`(my.dt, , sum(dependent.variable), by = grouping.vars[i] : 
    by must evaluate to list 

embargo, los siguientes trabajos sin error:

my.dt[,sum(dependent.variable), by=sex] 

veo por qué se produce el error, pero no veo cómo usar un vector con el parámetro by.

+0

Tiene dos "grouping.vars" pero itera desde 1: 5. ¿Me estoy perdiendo algo allí? – Shane

+1

Además, en su ejemplo de trabajo, el sexo es un objeto, mientras que en la versión que falla es un personaje. – Shane

+0

Hola Shane, lo siento, lo arreglé. Debería ser 2 no 5. Eso es lo que no tengo claro, parece que el sexo es un objeto (??). –

Respuesta

4

Me hicieron dos cambios en su código original:

sex <- c("M","F","M","F") 
age <- c(19, 23, 26, 21) 

age<-as.factor(age) 

dependent.variable <- c(1400, 1500, 1250, 1100) 
my.dt <- data.table(sex, age, dependent.variable) 

for (a in 1:2){ 
print(my.dt[,sum(dependent.variable), by=list(sex,age)[a]]) 
} 

vector numérico age debería ser forzado a factores. En cuanto al parámetro by, no utilice comillas para los nombres de las columnas, sino agrúpelas en la lista (...). Al menos esto es lo que el autor ha sugerido.

+0

Eso es interesante, y el diseño detrás del "por" parece un poco contradictorio, pero su código funciona principalmente. Solo un pequeño problema (menor y fácil de arreglar al asignar nombres en el bucle), los nombres de las columnas no se actualizan. Para sexo variable, los nombres son: sexo V1 Para la edad variable, los nombres son: sexo V1 –

5

[ACTUALIZACIÓN] se le pidió 2 años después de la pregunta ...

Al ejecutar el código en la pregunta, data.table es ahora más útil y devuelve este (usando 1.8.2):

Error in `[.data.table`(my.dt, , sum(dependent.variable), by = grouping.vars[i]) : 
    'by' appears to evaluate to column names but isn't c() or key(). Use by=list(...) 
    if you can. Otherwise, by=eval(grouping.vars[i]) should work. This is for efficiency 
    so data.table can detect which columns are needed. 

y siguiendo el consejo en la segunda frase de error:

my.dt[,sum(dependent.variable), by=eval(grouping.vars[i])] 
    sex V1 
1: M 2650 
2: F 2600 



vieja respuesta de Jul 2010 (by ahora puede ser double y character, sin embargo):

En rigor las necesidades by para evaluar a una lista de vectores, cada uno con número entero modo de almacenamiento, sin embargo. Por lo tanto, el vector numérico age también se puede forzar a un número entero usando as.integer(). Esto se debe a que data.table utiliza la ordenación de radix (muy rápido) pero el algoritmo de radix es específicamente para enteros solo (consulte la entrada de wikipedia para 'radix sort'). El almacenamiento entero para columnas clave y ad hoc by es una de las razones por las que data.table es rápido. Un factor es, por supuesto, una búsqueda entera de cadenas únicas.

La idea detrás de by es que list() de expresiones es que no está restringido a los nombres de columna. Es habitual escribir expresiones de nombres de columna directamente en el by. Uno común es agregar por mes; por ejemplo:

DT[,sum(col1), by=list(region,month(datecol))] 

o una manera muy rápida de grupo por yearmonth es mediante el uso de una fecha no basado época, como yyyymmddL como se ve en algunos de los ejemplos en el paquete, como este:

DT[,sum(col1), by=list(region,month=datecol%/%100L)] 

Observe cómo puede nombrar las columnas dentro de la lista() de esa manera.

Definir y reutilización de expresiones complejas de agrupación:

e = quote(list(region,month(datecol))) 
DT[,sum(col1),by=eval(e)] 
DT[,sum(col2*col3/col4),by=eval(e)] 

O si no desea volver a evaluar las expresiones by cada vez, puede guardar el resultado de una vez y volver a utilizar el resultado de la eficiencia; Si las expresiones by mismos tardan mucho tiempo para calcular/asignar o debe volver a usar muchas veces:

byval = DT[,list(region,month(datecol))] 
DT[,sum(col1),by=byval] 
DT[,sum(col2*col3/col4),by=byval] 

favor ver http://datatable.r-forge.r-project.org/ para la información más reciente y el estado. Una nueva presentación estará allí pronto y esperamos lanzar v1.5 a CRAN pronto también. Esto contiene varias correcciones de errores y nuevas características detalladas en el archivo NEWS. La lista de ayuda de tabla de datos tiene alrededor de 30-40 publicaciones al mes que también pueden ser de interés.

Cuestiones relacionadas