peut de la valeur.var dans dcast être une liste ou avoir plusieurs variables de valeur?

Dans les fichiers d'aide de dcast.data.table, Il y a une note indiquant qu'une nouvelle fonctionnalité a été implémentée: "dcast.données.la table autorise la valeur.var colonne à être de type list "

Je prends cela pour signifier que l'on peut avoir plusieurs variables de valeur dans une liste, c'est-à-dire dans ce format:

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

, Mais nous obtenons une erreur: 'value.var' must be a character vector of length 1.

Existe-t-il une telle fonctionnalité, et sinon, quelles seraient les autres alternatives à un seul revêtement?

EDIT: En réponse aux commentaires ci-dessous

Il y a des situations où vous avez plusieurs variables que vous voulez traiter comme value.var. Imaginez par exemple que x2 se compose de 3 semaines différentes, et que vous avez 2 variables de valeur telles que la consommation de sel et de sucre et que vous voulez lancer ces variables sur les différentes semaines. Bien sûr, vous pouvez "fondre" les variables de valeur 2 en une seule colonne, mais pourquoi faire quelque chose en utilisant deux fonctions, alors que vous pouvez le faire dans une fonction comme le fait reshape?

(Note: j'ai aussi remarqué que reshape ne peut pas traiter plusieurs variables comme la variable temporelle comme le fait dcast.)

Donc, mon point est que je ne comprends pas pourquoi ces fonctions ne permettent pas la flexibilité d'inclure plusieurs variables dans le value.var ou le time.var tout comme nous autorisons plusieurs variables pour le id.var.

27
demandé sur AlexR 2014-04-14 13:17:31

3 réponses

De v1. 9. 6 des données.table, nous pouvons lancer plusieurs colonnes value.var simultanément (et utiliser également plusieurs fonctions d'agrégation dans fun.aggregate). Veuillez consulter ?dcast et le Remodelage efficace à l'aide de données.tables vignette pour plus.

Voici comment nous pourrions utiliser 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
29
répondu Arun 2016-04-15 10:01:26

Mettre à jour

Apparemment, le correctif était beaucoup plus facile ...


Techniquement, votre déclaration selon laquelle "apparemment il n'y a pas une telle fonctionnalité" n'est pas tout à fait correcte. Il y a une telle fonctionnalité dans la fonction recast (qui cache en quelque sorte le processus de fusion et de coulée), mais il semble que Hadley ait oublié de terminer la fonction ou quelque chose: la fonction renvoie un list des parties pertinentes de votre opération.

Voici un minimum exemple...

Quelques exemples de données:

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

L'effet que vous semblez essayer de réaliser:

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 action. (Notez que les valeurs sont toutes ce que nous attendons dans les dimensions que nous attendons.)

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

Honnêtement, je ne suis pas sûr si c'était une fonction incomplète, ou si c'est une fonction d'aide à une autre fonction.

Toutes les informations sont là pour pouvoir remettre les données ensemble, ce qui facilite l'écriture d'une fonction comme ce:

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

Encore une fois, un avantage possible avec l'approche recast2 est la capacité d'agréger et de remodeler dans la même étape.

10
répondu A5C1D2H2I1M1N2O1R2T1 2014-04-22 15:24:35

En utilisant l'exemple de trame de données mydf à partir de la réponse de a5c1d2h2i1m1n2o1r2t1 .

Modifier décembre 2016 en utilisant tidyr

Reshape2 a été remplacé par le paquet 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

Réponse originale basée sur reshape2

@ AlexR a ajouté à sa question:

Bien sûr, vous pouvez 'fondre' les 2 variables de valeur en une seule colonne,

Pour ceux qui viennent ici à la recherche d'une réponse basée sur reshape2, voici comment faire fondre le données et ensuite utiliser dcast basé sur la "variable". .

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

La colonne variable contiendra maintenant 'var1', 'var2','var3'. Vous pouvez obtenir l'effet désiré avec

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

Valeur.var est facultatif dans cet appel de fonction car dcast le devine automatiquement.

8
répondu Paul Rougieux 2018-09-21 09:08:18