Преобразование фрейма данных в матрицу с plyr daply
Я пытаюсь использовать функцию daply
в пакете plyr
, но я не могу получить ее правильно. Хотя переменная, составляющая матрицу, является числовой, элементы матрицы представляют собой списки, а не сама переменная. Вот небольшое подмножество данных, например, саке:
Month Vehicle Samples
1 Oct-10 31057 256
2 Oct-10 31059 316
3 Oct-10 31060 348
4 Nov-10 31057 267
5 Nov-10 31059 293
6 Nov-10 31060 250
7 Dec-10 31057 159
8 Dec-10 31059 268
9 Dec-10 31060 206
И я хотел бы иметь возможность визуализировать данные в матричном формате, который будет выглядеть примерно так:
Month
Vehicle Oct-10 Nov-10 Dec-10
31057 256 267 159
31059 316 293 268
31060 348 250 206
Вот несколько альтернативных синтаксисов, которые я использую (последний из-за того, что в моем исходном фрейме данных больше столбцов, чем показано здесь):
daply(DF, .(Vehicle, Month), identity)
daply(DF,.(Vehicle,Month), colwise(identity,.(Samples)))
Однако то, что я получаю вместо этого, довольно заумно:
Month
Vehicle Oct-10 Nov-10 Dec-10
31057 List,3 List,3 List,3
31059 List,3 List,3 List,3
31060 List,3 List,3 List,3
Я использовал функцию str
на выходе, как предложили некоторые комментаторы, и вот выдержка:
List of 9
$ :'data.frame': 1 obs. of 3 variables:
..$ Month : Ord.factor w/ 3 levels "Oct-10"<"Nov-10"<..: 1
..$ Vehicle: Factor w/ 3 levels "31057","31059",..: 1
..$ Samples: int 256
$ :'data.frame': 1 obs. of 3 variables:
..$ Month : Ord.factor w/ 3 levels "Oct-10"<"Nov-10"<..: 1
..$ Vehicle: Factor w/ 3 levels "31057","31059",..: 2
..$ Samples: int 316
Что мне не хватает? Кроме того, есть ли способ сделать это просто с базовыми пакетами? Спасибо!
Ниже Dput
кадра данных, если вы хотите воспроизвести это:
structure(list(Month = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 3L,
3L, 3L), .Label = c("Oct-10", "Nov-10", "Dec-10"), class = c("ordered",
"factor")), Vehicle = structure(c(1L, 2L, 3L, 1L, 2L, 3L, 1L,
2L, 3L), .Label = c("31057", "31059", "31060"), class = "factor"),
Samples = c(256L, 316L, 348L, 267L, 293L, 250L, 159L, 268L,
206L)), .Names = c("Month", "Vehicle", "Samples"), class = "data.frame", row.names = c(NA,
9L))
Ответы
Ответ 1
Функция identity
не то, что вы хотите здесь; со страницы справки: "Все функции plyr используют одну и ту же стратегию split-apply-comb: они разбивают вход на более простые части, применяют .fun к каждой части, а затем объединяют фрагменты в единую структуру данных". Более простые части в этом случае являются подмножествами исходного фрейма данных с уникальными комбинациями Vehicle/Month; функция идентификации просто возвращает это подмножество, и эти подмножества затем используются для заполнения результирующей матрицы.
То есть каждый элемент полученной вами матрицы представляет собой кадр данных (который является типом списка) с строками с этой комбинацией "Месяц/Транспорт".
> try1 <- daply(DF, .(Vehicle, Month), identity)
> try1[1,1]
[[1]]
Month Vehicle Samples
1 Oct-10 31057 256
Вместо этого вы хотите использовать функцию, которая просто получает часть Samples
этого кадра данных, например:
daply(DF, .(Vehicle, Month), function(x) x$Samples)
что приводит к
Month
Vehicle Oct-10 Nov-10 Dec-10
31057 256 267 159
31059 316 293 268
31060 348 250 206
Несколько альтернативных способов сделать это: cast
из пакета reshape
(который возвращает фрейм данных)
cast(DF, Vehicle~Month, value="Samples")
пересмотренная версия в reshape2
; первый возвращает кадр данных, второй - матрицу
dcast(DF, Vehicle~Month, value_var="Samples")
acast(DF, Vehicle~Month, value_var="Samples")
с xtabs
из пакета stats
xtabs(Samples ~ Vehicle + Month, DF)
или вручную, что совсем не сложно с помощью матричной индексации; почти весь код просто устанавливает матрицу.
with(DF, {
out <- matrix(nrow=nlevels(Vehicle), ncol=nlevels(Month),
dimnames=list(Vehicle=levels(Vehicle), Month=levels(Month)))
out[cbind(Vehicle, Month)] <- Samples
out
})
Функция reshape
в пакете статистики также может быть использована для этого, но синтаксис затруднен, и я не использовал его один раз после обучения cast
и melt
из пакета reshape
.
Ответ 2
Если мы возьмем OP по их слову (именам) в названии, то они могут искать data.matrix()
, который является стандартной функцией в пакете base, который всегда доступен в R.
data.matrix()
работает путем преобразования любых факторов в их числовое кодирование перед преобразованием кадра данных в матрицу. Рассмотрим следующий фрейм данных:
dat <- data.frame(A = 1:10, B = factor(sample(c("X","Y"), 10, replace = TRUE)))
Если мы преобразуем через as.matrix()
, мы получим матрицу символов:
> head(as.matrix(dat))
A B
[1,] " 1" "X"
[2,] " 2" "X"
[3,] " 3" "Y"
[4,] " 4" "Y"
[5,] " 5" "Y"
[6,] " 6" "Y"
или если через matrix()
получается список с размерами (массив списка - как указано в разделе "Значение" ?daply
кстати)
> head(matrix(dat))
[,1]
[1,] Integer,10
[2,] factor,10
> str(matrix(dat))
List of 2
$ : int [1:10] 1 2 3 4 5 6 7 8 9 10
$ : Factor w/ 2 levels "X","Y": 1 1 2 2 2 2 1 2 2 1
- attr(*, "dim")= int [1:2] 2 1
data.matrix()
, однако, имеет смысл:
> mat <- data.matrix(dat)
> head(mat)
A B
[1,] 1 1
[2,] 2 1
[3,] 3 2
[4,] 4 2
[5,] 5 2
[6,] 6 2
> str(mat)
int [1:10, 1:2] 1 2 3 4 5 6 7 8 9 10 ...
- attr(*, "dimnames")=List of 2
..$ : NULL
..$ : chr [1:2] "A" "B"