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
.
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
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.
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.
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