Почему Саппли возвращает матрицу, которую мне нужно транспонировать, и тогда транспонированная матрица не будет прикреплена к кадру данных? - PullRequest
9 голосов
/ 10 ноября 2010

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

Когда я использую sapply, я хотел бы, чтобы он возвращал матрицу 3x2, но он возвращает матрицу 2x3.Почему это?И почему трудно прикрепить это к другому фрейму данных?

a <- data.frame(id=c('a','b','c'), var1 = c(1,2,3), var2 = c(3,2,1))
out <- sapply(a$id, function(x) out = a[x, c('var1', 'var2')])
#out is 3x2, but I would like it to be 2x3
#I then want to append t(out) (out as a 2x3 matrix) to b, a 1x3 dataframe
b <- data.frame(var3=c(0,0,0))

, когда я пытаюсь прикрепить их,

b[,c('col2','col3')] <- t(out)

Я получаю ошибку:

Warning message:
In `[<-.data.frame`(`*tmp*`, , c("col2", "col3"), value = list(1,  :
  provided 6 variables to replace 2 variables

хотя, как представляется, для получения желаемого результата:

rownames(out) <- c('col1', 'col2')
b <- cbind(b, t(out))

Я не могу работать с переменными:

b$var1/b$var2

возвращает

Error in b$var1/b$var2 : non-numeric argument to binary operator

Спасибо!

Ответы [ 3 ]

5 голосов
/ 10 ноября 2010

Чтобы расширить ответ DWin: это поможет взглянуть на структуру вашего out объекта.Это объясняет, почему b$var1/b$var2 не выполняет то, что вы ожидаете.

> out <- sapply(a$id, function(x) out = a[x, c('var1', 'var2')])
> str(out)  # this isn't a data.frame or a matrix...
List of 6
 $ : num 1
 $ : num 3
 $ : num 2
 $ : num 2
 $ : num 3
 $ : num 1
 - attr(*, "dim")= int [1:2] 2 3
 - attr(*, "dimnames")=List of 2
  ..$ : chr [1:2] "var1" "var2"
  ..$ : NULL

Семейство функций apply предназначено для работы с векторами и массивами, поэтому вам необходимо соблюдать осторожность при использовании их с данными.frames (обычно это списки векторов).Вы можете использовать тот факт, что data.frames являются списками в ваших интересах с lapply.

> out <- lapply(a$id, function(x) a[x, c('var1', 'var2')])  # list of data.frames
> out <- do.call(rbind, out) # data.frame
> b <- cbind(b,out)
> str(b)
'data.frame':   3 obs. of  4 variables:
 $ var3: num  0 0 0
 $ var1: num  1 2 3
 $ var2: num  3 2 1
 $ var3: num  0 0 0
> b$var1/b$var2
[1] 0.3333333 1.0000000 3.0000000
3 голосов
/ 10 ноября 2010

Сначала немного обозначений R. Если вы посмотрите на код для sapply, вы найдете ответ на свой вопрос. Функция sapply проверяет, все ли длины списков равны, и если да, то сначала их "unlist ()", а затем принимает эту серию списков в качестве аргумента данных для array(). Так как array (как matrix ()) по умолчанию размещает свои значения в главном порядке столбцов, это то, что вы получаете. Списки переворачиваются на их сторону. Если вам это не нравится, вы можете определить новую функцию tsapply, которая будет возвращать транспонированные значения:

> tsapply <- function(...) t(sapply(...))
> out <- tsapply(a$id, function(x) out = a[x, c('var1', 'var2')])
> out
     var1 var2
[1,] 1    3   
[2,] 2    2   
[3,] 3    1 

... матрица 3 x 2.

1 голос
/ 10 ноября 2010

Посмотрите на ddply из пакета plyr

a <- data.frame(id=c('a','b','c'), var1 = c(1,2,3), var2 = c(3,2,1))

library(plyr)
ddply(a, "id", function(x){
    out <- cbind(O1 = rnorm(nrow(x), x$var1), O2 = runif(nrow(x)))
    out
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...