czy wartość.var w dcast jest listą lub ma wiele zmiennych wartości?

W plikach pomocy dla dcast.data.table znajduje się notatka informująca o zaimplementowaniu nowej funkcji: "dcast.data.tabela pozwala na wartość.var column to be of type list "

Rozumiem, że można mieć wiele zmiennych wartości w liście, tzn. w tym formacie:

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

Ale dostajemy błąd: 'value.var' must be a character vector of length 1.

Czy istnieje taka funkcja, a jeśli nie, to jakie byłyby inne jednowarstwowe alternatywy?

EDIT: w odpowiedzi na komentarze poniżej

Są sytuacje, w których masz wiele zmiennych, które chcesz traktować jako value.var. Wyobraź sobie na przykład, że x2 składa się z 3 różnych tygodni i masz 2 zmienne wartości, takie jak spożycie soli i cukru i chcesz rzucić te zmienne w różnych tygodniach. Oczywiście, możesz "stopić" 2 zmienne wartości w jedną kolumnę, ale po co robić coś za pomocą dwóch funkcji, skoro możesz to zrobić w jednej funkcji, jak robi to reshape?

(uwaga: zauważyłem również, że reshape nie można traktować wielu zmiennych jako zmiennych czasowych, tak jak robi to dcast.)

Chodzi mi więc o to, że nie rozumiem, dlaczego te funkcje nie pozwalają na elastyczność, aby zawierać wiele zmiennych w value.var lub time.var, tak jak pozwalamy na wiele zmiennych dla id.var.

Author: AlexR, 2014-04-14

3 answers

Z v1.9.6 danych.table, możemy rzucać Wiele value.var kolumn jednocześnie (a także używać wielu funkcji agregujących w fun.aggregate). Zobacz ?dcast i efektywne przekształcanie danych.tabele winieta więcej.

Oto jak możemy użyć 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
Author: Arun,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-15 10:01:26

Update

Najwyraźniej, naprawa była znacznie łatwiejsza ...


Technicznie, Twoje stwierdzenie, że "najwyraźniej nie ma takiej funkcji" nie jest całkiem {17]} poprawne. Istnieje taka funkcja w funkcji recast (która ukrywa proces topienia i odlewania), ale wygląda na to, że Hadley zapomniał zakończyć funkcję lub coś takiego: funkcja zwraca list odpowiednich części operacji.

Oto Minimalne przykład...

Niektóre przykładowe dane:

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

Efekt, który próbujesz osiągnąć:

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 w akcji. (Zauważ, że wartości są tym, czego oczekujemy w wymiarach, których oczekujemy.)

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

Szczerze mówiąc nie jestem pewien, czy była to funkcja niekompletna, czy też jest funkcją pomocniczą do innej funkcji.

Wszystkie informacje są tam, aby móc umieścić dane z powrotem razem, co ułatwia pisanie funkcji, takich jak to:

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

Ponownie, możliwą zaletą z podejściem recast2 jest zdolność do agregacji, jak również przekształcania w tym samym kroku.

 10
Author: A5C1D2H2I1M1N2O1R2T1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-22 15:24:35

Użycie przykładowej ramki danych mydf z odpowiedzi A5C1D2H2I1M1N2O1R2T1 .

Edycja grudzień 2016 przy użyciu tidyr

Reshape2 został zastąpiony pakietem 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

Oryginalna odpowiedź na podstawie reshape2

@ AlexR dodał do pytania:

Oczywiście, możesz "stopić" 2 zmienne wartości w jedną kolumnę,

Dla tych, którzy przychodzą tu szukać odpowiedzi na podstawie reshape2, Oto Jak stopić danych, a następnie użyć dcast na podstawie "zmiennej". .

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

Kolumna zmiennej będzie teraz zawierać 'var1', 'var2', 'var3'. Możesz osiągnąć pożądany efekt za pomocą

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

Wartość.var jest opcjonalne w tym wywołaniu funkcji, ponieważ dcast automatycznie go odgadnie.

 8
Author: Paul Rougieux,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-21 09:08:18