R语言 使用apply返回扩展矩阵

vsmadaxz  于 2023-11-14  发布在  其他
关注(0)|答案(3)|浏览(87)

我有一个我试图使用apply的矩阵,但是我的函数采用10x1矩阵,然后返回10x2矩阵(即calaculates 2 values for each inout value).我的整体矩阵是10x3所以当我使用apply()我应该得到一个10x6矩阵,但是我不能得到apply()添加更多的列,这是可能的apply()?我的函数产生一个10x2,但是当我调用apply()时,第二列被截断了。

data_matrix <- function(column) {
  polynomial <- poly(column, degree=2, raw=TRUE)
  return(polynomial)
}
poly_matrix <- apply(test_data, 2, data_matrix)

字符串

q3aa0525

q3aa05251#

apply不要简化它的输出。这是通过将参数simplify设置为FALSE来调用它来完成的。
另一种方法是直接使用lapply,但这仅在输入是 Dataframe 时才可能,如果输入数据是"matrix"类,则必须使用apply

data_matrix <- function(column) {
  polynomial <- poly(column, degree = 2L, raw = TRUE)
  polynomial
}

# make the input data and the results reproducible
set.seed(2023)
# test data
test_data <- replicate(3L, rnorm(5L)) |> as.data.frame()

# change argument 'simplify' default to get a list,
# then cbind the list members to form a matrix
poly_matrix <- apply(test_data, 2L, data_matrix, simplify = FALSE)
do.call(cbind, poly_matrix)
#>                1           2          1         2          1         2
#> [1,] -0.08378436 0.007019818  1.0907975 1.1898391  0.3269621 0.1069042
#> [2,] -0.98294375 0.966178406 -0.9137273 0.8348975 -0.4127469 0.1703600
#> [3,] -1.87506732 3.515877460  1.0016397 1.0032821  0.5620365 0.3158850
#> [4,] -0.18614466 0.034649835 -0.3992666 0.1594138  0.6633583 0.4400442
#> [5,] -0.63348570 0.401304130 -0.4681231 0.2191392 -0.6028973 0.3634851

# lapply returns a list of the matrices output by the called function
poly_matrix <- lapply(test_data, data_matrix)
do.call(cbind, poly_matrix)
#>                1           2          1         2          1         2
#> [1,] -0.08378436 0.007019818  1.0907975 1.1898391  0.3269621 0.1069042
#> [2,] -0.98294375 0.966178406 -0.9137273 0.8348975 -0.4127469 0.1703600
#> [3,] -1.87506732 3.515877460  1.0016397 1.0032821  0.5620365 0.3158850
#> [4,] -0.18614466 0.034649835 -0.3992666 0.1594138  0.6633583 0.4400442
#> [5,] -0.63348570 0.401304130 -0.4681231 0.2191392 -0.6028973 0.3634851

# a pipe to do.call will do any of the above in one code line only
apply(test_data, 2L, data_matrix, simplify = FALSE) |> do.call(cbind, args = _)
#>                1           2          1         2          1         2
#> [1,] -0.08378436 0.007019818  1.0907975 1.1898391  0.3269621 0.1069042
#> [2,] -0.98294375 0.966178406 -0.9137273 0.8348975 -0.4127469 0.1703600
#> [3,] -1.87506732 3.515877460  1.0016397 1.0032821  0.5620365 0.3158850
#> [4,] -0.18614466 0.034649835 -0.3992666 0.1594138  0.6633583 0.4400442
#> [5,] -0.63348570 0.401304130 -0.4681231 0.2191392 -0.6028973 0.3634851

lapply(test_data, data_matrix) |> do.call(cbind, args = _)
#>                1           2          1         2          1         2
#> [1,] -0.08378436 0.007019818  1.0907975 1.1898391  0.3269621 0.1069042
#> [2,] -0.98294375 0.966178406 -0.9137273 0.8348975 -0.4127469 0.1703600
#> [3,] -1.87506732 3.515877460  1.0016397 1.0032821  0.5620365 0.3158850
#> [4,] -0.18614466 0.034649835 -0.3992666 0.1594138  0.6633583 0.4400442
#> [5,] -0.63348570 0.401304130 -0.4681231 0.2191392 -0.6028973 0.3634851

字符串
创建于2023-11-11使用reprex v2.0.2

编辑

在更仔细地阅读文档之后,似乎apply的这种行为是一个设计决策。文档首先提到了返回向量的函数。引用自help("apply"),Value部分,我的重点。
如果每次调用FUN都返回一个长度为nvector,并且simplify为TRUE,则如果n > 1,则apply返回一个维度为c(n, dim(X)[MARGIN])的数组。如果n等于1,则如果MARGIN的长度为1,则apply返回一个向量,否则返回一个维度为dim(X)[MARGIN]的数组。如果n为0,结果的长度为0,但不一定是“正确的”尺寸。
然后,在最后一段中,我强调:
在所有情况下,在设置维度之前,结果都被as.vector**强制转换为一种基本向量类型,因此(例如)因子结果将被强制转换为字符数组。
这解释了为什么使用默认值simplify = TRUE的调用返回一个矩阵,其中dim[1L]是输入向量长度的两倍。如果它是原子模式,则所有属性都将从结果中删除as.vector。数值矩阵就是这种情况,它们是具有dim属性的原子向量,因此被删除,变成向量ncol乘以长度(在问题的情况下是两倍)。

iswrvxsc

iswrvxsc2#

如果你使用sapply,你可以简单地通过旧尺寸乘以c(1, deg)来重新排列array

> deg <- 2
> sapply(dat, poly, degree=deg, raw=TRUE) |> array(dim=dim(dat)*c(1, deg))
            [,1]        [,2]       [,3]      [,4]       [,5]      [,6]
[1,] -0.08378436 0.007019818  1.0907975 1.1898391  0.3269621 0.1069042
[2,] -0.98294375 0.966178406 -0.9137273 0.8348975 -0.4127469 0.1703600
[3,] -1.87506732 3.515877460  1.0016397 1.0032821  0.5620365 0.3158850
[4,] -0.18614466 0.034649835 -0.3992666 0.1594138  0.6633583 0.4400442
[5,] -0.63348570 0.401304130 -0.4681231 0.2191392 -0.6028973 0.3634851

字符串
Package 成函数

> extend <- \(dat, deg=2) {
+   sapply(as.data.frame(dat), poly, degree=deg, raw=TRUE) |> 
+     array(dim=dim(dat)*c(1, deg))
+ }
> 
> extend(dat)
            [,1]        [,2]       [,3]      [,4]       [,5]      [,6]
[1,] -0.08378436 0.007019818  1.0907975 1.1898391  0.3269621 0.1069042
[2,] -0.98294375 0.966178406 -0.9137273 0.8348975 -0.4127469 0.1703600
[3,] -1.87506732 3.515877460  1.0016397 1.0032821  0.5620365 0.3158850
[4,] -0.18614466 0.034649835 -0.3992666 0.1594138  0.6633583 0.4400442
[5,] -0.63348570 0.401304130 -0.4681231 0.2191392 -0.6028973 0.3634851


请注意,apply是为矩阵设计的,与lapply; sapply; vapply相反,对于 Dataframe 来说速度较慢。

  • 数据:*
> dput(dat)
structure(list(V1 = c(-0.0837843554981313, -0.982943745280687, 
-1.8750673214048, -0.186144660710734, -0.63348569815203), V2 = c(1.09079746414669, 
-0.913727274142924, 1.00163971155077, -0.399266603219373, -0.468123054013521
), V3 = c(0.32696208288009, -0.41274689835186, 0.562036469443693, 
0.663358259979942, -0.602897283941171)), class = "data.frame", row.names = c(NA, 
-5L))

yr9zkbsy

yr9zkbsy3#

有了商定的数据,我会把这个放在未来,以提醒自己在所有 Package 之前发生了什么

poly_res = poly(as.matrix(dat), degree = 2, raw = TRUE)[1:5, c(1:3, 5:6, 9)]
> dimnames(poly_res) <- list(NULL, 1:6)
> poly_res
               1           2          3         4          5         6
[1,] -0.08378436 0.007019818  1.0907975 1.1898391  0.3269621 0.1069042
[2,] -0.98294375 0.966178406 -0.9137273 0.8348975 -0.4127469 0.1703600
[3,] -1.87506732 3.515877460  1.0016397 1.0032821  0.5620365 0.3158850
[4,] -0.18614466 0.034649835 -0.3992666 0.1594138  0.6633583 0.4400442
[5,] -0.63348570 0.401304130 -0.4681231 0.2191392 -0.6028973 0.3634851

字符串
数据

dat = structure(list(V1 = c(-0.0837843554981313, -0.982943745280687, 
-1.8750673214048, -0.186144660710734, -0.63348569815203), V2 = c(1.09079746414669, 
-0.913727274142924, 1.00163971155077, -0.399266603219373, -0.468123054013521
), V3 = c(0.32696208288009, -0.41274689835186, 0.562036469443693, 
0.663358259979942, -0.602897283941171)), class = "data.frame", row.names = c(NA,
-5L))


我认为上面的答案很棒,但是掩盖了poly所做的接近你想要的结果(额外的,不想要的输出),提供了一个从输出中选择想要的结果的机会。一年后回到这个问题,我可能无法回忆起poly正在做繁重的工作。

相关问题