¿el valor.var en dcast puede ser una lista o tener múltiples variables de valor?
data.table reshape (3)
En los archivos de ayuda para 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"
Entiendo 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, de no ser así, 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 varias variables que desea tratar como value.var
. Imagina, por ejemplo, que x2 consta de 3 semanas diferentes, y tienes 2 variables de valor como el consumo de sal y azúcar y quieres repartir esas variables en las diferentes semanas. Claro, puedes ''fundir'' las 2 variables de valor en una sola columna, pero ¿por qué hacer algo con dos funciones, cuando puedes hacerlo en una función como lo hace la reshape
?
(Nota: También he notado que la reshape
no puede tratar múltiples variables como la variable de tiempo como dcast
hace el dcast
).
Así que mi punto es que no entiendo por qué estas funciones no permiten la flexibilidad de incluir múltiples variables dentro de value.var
o time.var
al igual que permitimos múltiples variables para id.var
.
Actualizar
Al parecer, 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. Hay una característica de este tipo en la función de recast
(que oculta el proceso de fusión y fundición), pero parece que Hadley se olvidó de finalizar la función o algo: 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 parece estar intentando 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 todos lo que esperaríamos en las dimensiones que lo 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 de 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 escritura de 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.
Desde v1.9.6 de data.table, podemos convertir varias columnas value.var
simultáneamente (y también usar múltiples funciones de agregación en fun.aggregate
). Para obtener más información, consulte ?dcast
y la " remodelación eficiente" utilizando la viñeta data.tables .
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
Usando el marco de datos de muestra mydf
de la respuesta de A5C1D2H2I1M1N2O1R2T1 .
Edición diciembre 2016 usando tidyr
Reshape2 ha sido reemplazado 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
Respuesta original basada en reshape2
@AlexR agregó a su pregunta:
Claro, puedes ''fundir'' las 2 variables de valor en una sola columna,
Para aquellos que vienen aquí en busca de una respuesta basada en reshape2 , aquí se explica cómo fundir los datos y luego usar el programa basado en la "variable". .
dt2 <- melt(mydf, id = c("x1", "x2"))
La columna de la variable ahora contendrá ''var1'', ''var2'', ''var3''. Puedes 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.