R 为什么sapply返回一个我需要转置的矩阵,然后转置的矩阵将不会附加到数据帧?

R 为什么sapply返回一个我需要转置的矩阵,然后转置的矩阵将不会附加到数据帧?,r,data-structures,vectorization,apply,R,Data Structures,Vectorization,Apply,我希望能够深入了解为什么会发生这种情况,以及我如何更雄辩地做到这一点 当我使用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, bu

我希望能够深入了解为什么会发生这种情况,以及我如何更雄辩地做到这一点

当我使用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))
返回

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

谢谢

首先是一点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 
>t向外应用
var1 var2
[1,] 1    3   
[2,] 2    2   
[3,] 3    1 

。。。一个3 x 2的矩阵。

来扩展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

查看plyr包装中的ddply

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
})

从技术上讲,
out
不是矩阵。它是一个具有
dim
dimnames
属性的列表。例如,
out%*%t(out)
失败。除非R认为它是一个矩阵:>是。矩阵(out)[1]真的。你想用这个数据做什么?您的示例实际上没有做任何有意义的事情。@哈德利:该示例遵循R发布指南,提供了一个最小的、可行的示例。实际情况相当复杂,其复杂性会影响核心问题。我的函数使用泰勒级数展开估计模型对20个不同参数的敏感性,并接受20x8数据帧作为输入。如果您愿意,我很乐意发送一个完整的可复制的示例,尽管它还没有准备好公开。您需要在易于理解的内容和抓住您正在努力解决的问题本质的内容之间寻求一个愉快的媒介。在您当前的示例中,您似乎试图使
b
等于
a
。@hadley:谢谢您的提示,我会记住的。
Error in b$var1/b$var2 : non-numeric argument to binary operator
> 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 
> 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
> 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
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
})