Подтвердить что ты не робот

Может ли value.var в dcast быть списком или иметь несколько переменных значений?

В файлах справки для dcast.data.table есть заметка о том, что была реализована новая функция: "dcast.data.table позволяет столбцу value.var иметь список типов"

Я полагаю, это означает, что в списке можно иметь несколько переменных значений, то есть в этом формате:

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

Но мы получаем ошибку: 'value.var' must be a character vector of length 1.

Есть ли такая особенность, а если нет, то какие альтернативы могут быть однолинейными?

EDIT: в ответ на комментарии ниже

Существуют ситуации, когда у вас есть несколько переменных, которые вы хотите рассматривать как value.var. Представьте себе, например, что x2 состоит из трех разных недель, и у вас есть 2 значения переменных, таких как потребление соли и сахара, и вы хотите использовать эти переменные в разные недели. Конечно, вы можете "расплавить" переменные значения 2 в один столбец, но зачем что-то использовать с помощью двух функций, когда вы можете сделать это с помощью одной функции, например reshape?

(Примечание. Я также заметил, что reshape не может обрабатывать несколько переменных как временную переменную, чем dcast).

Итак, я хочу сказать, что я не понимаю, почему эти функции не позволяют гибко включать несколько переменных в value.var или time.var так же, как мы допускаем несколько переменных для id.var.

4b9b3361

Ответ 1

Из v1.9.6 таблицы data.table мы можем использовать несколько столбцов value.var одновременно (а также использовать несколько функций агрегации в fun.aggregate). См. ?dcast и Эффективная перестройка с использованием data.tables виньетки для более.

Здесь мы можем использовать 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

Ответ 2

Update

По-видимому, исправление было намного проще...


Технически ваше утверждение о том, что "по-видимому, нет такой возможности", не совсем корректно. В функции recast есть такая особенность (которая скрывает процесс плавления и литья), но похоже, что Хэдли забыл закончить функцию или что-то еще: функция возвращает list соответствующих частей вашей операции.

Здесь минимальный пример...

Некоторые примеры данных:

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

Эффект, который вы пытаетесь достичь:

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 в действии. (Обратите внимание, что значения - это все, чего мы ожидаем в размерах, которые мы ожидали бы.)

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

Я честно не уверен, что это была неполная функция, или если это вспомогательная функция для другой функции.

Вся информация содержит возможность повторного объединения данных, что упрощает запись такой функции:

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

Опять же, возможным преимуществом с подходом recast2 является способность агрегировать, а также изменять на том же этапе.

Ответ 3

@AlexR добавил к своему вопросу:

Конечно, вы можете "расплавить" переменные значения 2 в один столбец,

Для тех, кто приходит сюда, ищет ответ на основе reshape2, вот как расплавить данные, а затем использовать dcast на основе "переменной". Использование данных образца из ответа @A_Handcart_And_Mohair.

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

В столбце переменной теперь будут содержаться "var1", "var2", "var3". Вы можете добиться желаемого эффекта с помощью

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

Значение .var является необязательным в этом вызове функции, поскольку dcast автоматически угадает его.

Изменить декабрь 2016

Теперь Reshape2 можно заменить на пакет 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