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

Dav*_*uer 9 r vectorization apply data-structures

我希望了解为什么会发生这种情况以及如何更有说服力地做到这一点.

当我使用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))
Run Code Online (Sandbox Code Playgroud)

当我试图附上这些时,

b[,c('col2','col3')] <- t(out)
Run Code Online (Sandbox Code Playgroud)

我得到的错误是:

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

虽然以下似乎给出了预期的结果:

rownames(out) <- c('col1', 'col2')
b <- cbind(b, t(out))
Run Code Online (Sandbox Code Playgroud)

我无法对变量进行操作:

b$var1/b$var2
Run Code Online (Sandbox Code Playgroud)

回报

Error in b$var1/b$var2 : non-numeric argument to binary operator
Run Code Online (Sandbox Code Playgroud)

谢谢!

Jos*_*ich 5

要扩展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
Run Code Online (Sandbox Code Playgroud)

该apply系列函数被设计为在向量和阵列工作,所以你需要照顾与data.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
Run Code Online (Sandbox Code Playgroud)