¿el valor.var en dcast puede ser una lista o tener múltiples variables de valor?

En los archivos de ayuda de dcast.data.table , hay una nota que indica que se ha implementado una nueva característica: “dcast.data.table permite que la columna value.var sea de tipo lista”

Considero que esto significa que uno puede tener múltiples variables de valor dentro de una lista, es decir, en este formato:

 dcast.data.table(dt, x1~x2, value.var=list('var1','var2','var3')) 

Pero obtenemos un error: 'value.var' must be a character vector of length 1.

¿Existe tal característica, y si no, cuáles serían otras alternativas de una sola línea?

EDITAR: En respuesta a los comentarios a continuación

Hay situaciones en las que tiene múltiples variables que desea tratar como el value.var . Imagine, por ejemplo, que x2 consta de 3 semanas diferentes, y tiene 2 variables de valor, como el consumo de sal y azúcar, y desea emitir esas variables a lo largo de las diferentes semanas. Claro, puedes ‘fundir’ las 2 variables de valor en una sola columna, pero ¿por qué hacer algo usando dos funciones, cuando puedes hacerlo en una función como lo hace la reshape ?

(Nota: también noté que la reshape no puede tratar múltiples variables como la variable de tiempo como dcast hace dcast ).

Así que mi punto es que no entiendo por qué estas funciones no permiten la flexibilidad de incluir múltiples variables dentro del value.var o el time.var misma forma que permitimos múltiples variables para el id.var .

Desde la v1.9.6 de data.table, podemos convertir múltiples columnas value.var simultáneamente (y también usar múltiples funciones de agregación en fun.aggregate ). Consulte ?dcast y la remodelación eficiente utilizando la viñeta de data.tables para obtener más información.

Así es como podríamos usar dcast :

 dcast(setDT(mydf), x1 ~ x2, value.var=c("salt", "sugar")) # x1 salt_1 salt_2 salt_3 sugar_1 sugar_2 sugar_3 # 1: 1 3 4 6 1 2 2 # 2: 2 10 3 9 5 3 6 # 3: 3 10 7 7 4 6 7 

Actualizar

Aparentemente, la solución fue mucho más fácil …


Técnicamente, su afirmación de que “aparentemente no existe tal característica” no es del todo correcta. Existe una característica de este tipo en la función de recast (que oculta el proceso de fundición y fundición), pero parece que Hadley olvidó terminar la función o algo así: la función devuelve una list de las partes relevantes de su operación.

Aquí hay un ejemplo mínimo …

Algunos datos de muestra:

 set.seed(1) mydf <- data.frame(x1 = rep(1:3, each = 3), x2 = rep(1:3, 3), salt = sample(10, 9, TRUE), sugar = sample(7, 9, TRUE)) mydf # x1 x2 salt sugar # 1 1 1 3 1 # 2 1 2 4 2 # 3 1 3 6 2 # 4 2 1 10 5 # 5 2 2 3 3 # 6 2 3 9 6 # 7 3 1 10 4 # 8 3 2 7 6 # 9 3 3 7 7 

El efecto que pareces tratar de lograr:

 reshape(mydf, idvar='x1', timevar='x2', direction='wide') # x1 salt.1 sugar.1 salt.2 sugar.2 salt.3 sugar.3 # 1 1 3 1 4 2 6 2 # 4 2 10 5 3 3 9 6 # 7 3 10 4 7 6 7 7 

recast en acción. (Tenga en cuenta que los valores son todo lo que esperaríamos en las dimensiones que esperaríamos).

 library(reshape2) out <- recast(mydf, x1 ~ x2 + variable, measure.var = c("salt", "sugar")) ### recast(mydf, x1 ~ x2 + variable, id.var = c("x1", "x2")) out # $data # [,1] [,2] [,3] [,4] [,5] [,6] # [1,] 3 1 4 2 6 2 # [2,] 10 5 3 3 9 6 # [3,] 10 4 7 6 7 7 # # $labels # $labels[[1]] # x1 # 1 1 # 2 2 # 3 3 # # $labels[[2]] # x2 variable # 1 1 salt # 2 1 sugar # 3 2 salt # 4 2 sugar # 5 3 salt # 6 3 sugar 

Honestamente, no estoy seguro si esta fue una función incompleta, o si es una función auxiliar para otra función.

Toda la información está allí para poder volver a juntar los datos, lo que facilita la tarea de escribir una función como esta:

 recast2 <- function(...) { inList <- recast(...) setNames(cbind(inList[[2]][[1]], inList[[1]]), c(names(inList[[2]][[1]]), do.call(paste, c(rev(inList[[2]][[2]]), sep = "_")))) } recast2(mydf, x1 ~ x2 + variable, measure.var = c("salt", "sugar")) # x1 salt_1 sugar_1 salt_2 sugar_2 salt_3 sugar_3 # 1 1 3 1 4 2 6 2 # 2 2 10 5 3 3 9 6 # 3 3 10 4 7 6 7 7 

De nuevo, una posible ventaja con el enfoque recast2 es la capacidad de agregar y remodelar en el mismo paso.

@AlexR agregó a su pregunta:

Claro, puedes ‘fundir’ las 2 variables de valor en una sola columna,

Para aquellos que vienen aquí buscando una respuesta basada en reshape2 , aquí se muestra cómo fundir los datos y luego usar dcast en función de la “variable”. Usando datos de muestra de la respuesta de @ A_Handcart_And_Mohair.

 dt2 <- melt(mydf, id = c("x1", "x2")) 

La columna variable contendrá ahora 'var1', 'var2', 'var3'. Puede lograr el efecto deseado con

 dt3 <- dcast(dt2, x1 ~ x2 + variable, value.var="value") dt3 # x1 1_salt 1_sugar 2_salt 2_sugar 3_salt 3_sugar # 1 1 3 1 4 2 6 2 # 2 2 10 5 3 3 9 6 # 3 3 10 4 7 6 7 7 

value.var es opcional en esta llamada de función ya que dcast lo adivinará automáticamente.

Edición de diciembre de 2016

Reshape2 ahora puede reemplazarse con el paquete tidyr .

 library(tidyr) mydf %>% gather(variable, value, -x1, -x2) %>% unite(x2_variable, x2, variable) %>% spread(x2_variable, value) # x1 1_salt 1_sugar 2_salt 2_sugar 3_salt 3_sugar # 1 1 3 1 4 2 6 2 # 2 2 10 5 3 3 9 6 # 3 3 10 4 7 6 7 7