Преобразование фрейма данных в матрицу с помощью plyr daply - PullRequest
7 голосов
/ 10 августа 2011

Я пытаюсь использовать функцию 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))

Ответы [ 2 ]

7 голосов
/ 11 августа 2011

Функция identity не то, что вы хотите здесь; со страницы справки: «Все функции plyr используют одну и ту же стратегию разделения-применения-объединения: они разбивают входные данные на более простые части, применяют .fun к каждой части, а затем объединяют части в единую структуру данных». Более простыми частями в этом случае являются подмножества исходного фрейма данных с уникальными комбинациями Автомобиль / Месяц; функция тождества просто возвращает это подмножество, и эти подмножества затем используются для заполнения результирующей матрицы.

То есть каждый элемент матрицы, которую вы получили, представляет собой фрейм данных (который является типом списка) со строками с этой комбинацией Месяц / Автомобиль.

> 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 в пакете stats также может быть использована для этого, но синтаксис сложен, и я не использовал его один раз с момента изучения cast и melt из пакета reshape.

2 голосов
/ 10 августа 2011

Если мы возьмем 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"
...