【问题标题】:How to multiply a vector by function output element by element in R如何将向量乘以函数输出元素在R中的元素
【发布时间】:2018-03-28 08:08:07
【问题描述】:

这个问题与我的问题有关:My old question

但是,在这个问题中,我想将一个向量元素乘以函数输出。

这是我的问题的描述:

想法

假设我有一个10 向量列表,并希望将每个向量乘以列的数组的特定值。也就是说,第一个向量值仅乘以每个数组的第一个元素。然后,第二个向量值只乘以每个数组的第二个元素。对所有向量都这样做。因为我有10 向量(每个都有100 值)和100 数组,所以每个都有10 非零值。然后,我想按照上面的描述进行一一相乘。

示例

  1. 取列表的第一个向量。 x[[1]] 然后将它的每个元素乘以数组的每个第一个元素。
  2. 然后第二个向量值乘以数组的每个第二个元素。
  3. 然后,第三个向量值乘以数组的每个第三个元素。
  4. 对所有其他向量执行此操作。

数值例子

假设我有一个向量列表,以下向量是我列表的第一个和第二个向量。

[[1]]
 [1] 2.174090 1.666464 1.915763 2.282967 2.407327 1.386437 2.854528 1.896338 2.010713 1.013387 .......... (`100` values)

[[2]]
 [1]  2.3020147  3.3311029 -0.3103701  3.2445878  5.6261224  5.2914477 -1.0621042  3.0790536  3.6186598
[10]  4.1846937 ........ (`100` values)

[[3]]
 [1]  0.42808525  4.02348551 -2.31160703  5.56077594  2.83856320 -0.02850242  1.57480238 -2.68603276
 [9]  2.34598854  4.14115289 ....(`100` values)

假设我有一个包含 10 值的数组列表 (100)。让我们下面的数组是我的数组列表的第一个和第二个数组。

, , 1

           [,1]        [,2]       [,3]      [,4] [,5]
[1,]  0.0000000  0.00000000  0.0000000  0.000000    0
[2,] -0.4610817  0.00000000  0.0000000  0.000000    0
[3,]  0.4697426 -0.07296078  0.0000000  0.000000    0
[4,] -0.2790043 -0.77459992 -0.7478920  0.000000    0
[5,] -0.2156273 -2.59804286 -0.9390597 -1.746925    0

    , , 2

            [,1]       [,2]       [,3]      [,4] [,5]
[1,]  0.00000000  0.0000000  0.0000000  0.000000    0
[2,] -0.21896586  0.0000000  0.0000000  0.000000    0
[3,] -0.09066381  0.2920374  0.0000000  0.000000    0
[4,]  1.27289131 -0.2748794  1.0862465  0.000000    0
[5,] -1.20050567 -1.0934879 -0.7707806 -2.180104    0

然后我想将第一个向量的第一个元素乘以数组的第一个非零值。即2.174090 * -0.4610817然后,第一个向量的第二个元素将乘以第二个数组的第一个元素,即1.666464 * -0.21896586。然后,第二个向量的第一个元素乘以第一个数组的第二个元素,即2.3020147 * 0.4697426 第二个向量的第二个元素乘以第二个数组的第二个元素3.3311029 * -0.09066381

第三个向量乘以数组的每个第三个元素。

0.42808525 * -0.2790043

即:

第一个向量的元素只乘以数组的第一个元素(一个接一个)。然后,第二个向量只乘以数组的第二个元素

代码:

set.seed(24)
myfun <- function(n, N){
  a <- array(rnorm(n * n * N), c(n, n, N))
  for(k in seq(dim(a)[3])) a[,,k][upper.tri(a[,,k], diag = TRUE)] <- 0
  out <- list()
  out$a <- a
  return(out)
}

我希望代码几乎只有一行。那是因为我有一个复杂的函数,其输出的形状与我的函数输出相似。

res <- sum(x* myfun(5,10)$a)

我试过了:

x <- rnorm(10,2,2)

x <- rep(list(x), 10)

res <- myfun(5,10)$a
res[res != 0] <- res[res != 0]*x[[1]]

但是,它没有按预期工作,我也想让代码不仅适用于列表x[[1]]

也就是说,我想先相乘再求和,得到一个值。

【问题讨论】:

  • 我不确定为什么单行是必需的。清晰可以很好,如果您的代码变得太长,请将其拆分为单独的函数。此外,逐个矩阵相乘是 R 中的默认功能,因此如果将两个数据集重塑为相同的维度,它应该会更简单。

标签: arrays r


【解决方案1】:

正如我在评论中所说,几行代码可以帮助清晰而不是模糊单行代码。

不过,对于您的问题,您可以利用 R 进行矢量化计算的事实,即对表的每个元素逐元素进行计算。

所以我会首先重塑数据。您的示例数据是这样的,如果我错了,请纠正我:

  • 维数为 (n, n, N) 的数组,您将其描述为具有 n×n 值的 N 个数组的“列表”,其中上三角为零:它们包含 p = n(n-1)/2 非零值;
  • p 长度为 N 的向量列表

输入数据:

N <- 10
n <- 3
p <- n*(n-1)/2  # = 3

veclist <- list(
  c(2.174090, 1.666464, 1.915763, 2.282967, 2.407327, 1.386437, 2.854528, 1.896338, 2.010713, 1.013387),
  c(2.3020147, 3.3311029, -0.3103701, 3.2445878, 5.6261224, 5.2914477, -1.0621042, 3.0790536, 3.6186598, 4.1846937),
  c(0.42808525, 4.02348551, -2.31160703, 5.56077594, 2.83856320, -0.02850242, 1.57480238, -2.68603276, 2.34598854, 4.14115289)
)

arr <- myfun(n, N)$a

重塑:

mat <- matrix(unlist(veclist), nrow=length(veclist), byrow=T)
dim(mat) # 3 10

# reformat the lower triangle data of arrays
flatarr <- sapply(1:N, function(i) arr[,,i][lower.tri(arr[,,i])])
dim(flatarr) # 3 10

进行元素乘法:

res <- mat * flatarr

所以实际上这只是重塑的问题。

说明

上面的sapply 行将相同的函数应用于10 个数组中的每一个。这个函数是:

function(i) {
    # take the array number `i`
    ai <- arr[,,i]
    # get the lower triangle values
    ai[lower.tri(ai)]
}

sapply 的输出会自动简化为一个维度为 (3, 10) 的矩阵,即 3 行 10 列。

扁平化数组时的注意事项:

R按列获取矩阵元素。如果你想要的顺序是按行,你必须转置数组并取upper.tri,所以sapply函数如下:

function(i) t(arr[,,i])[upper.tri(t(arr[,,i]))]

单线

(一旦你定义了veclistarr &lt;- myfun(n,N)$a

res <- matrix(unlist(veclist), nrow=length(veclist), byrow=T) * sapply(1:N, function(i) arr[,,i][lower.tri(arr[,,i])])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-12
    • 1970-01-01
    • 2021-12-05
    • 1970-01-01
    相关资源
    最近更新 更多