在R中不使用循环对元素求和

时间:2018-01-20 20:31:03

标签: r string

说我有数字字符串

str1 <- c(1, 2, 3)str2 <- c(4, 7, 10, 18, 20)

和一组数据hex_np <- c(2, 4, 6, 8, 10)

我想在str1[a] * hex_np + str2[b]a=1,2,3中显示每个b=1,2,3,4,5

即,

str1[1] * hex_np + str2[1]str1[1] * hex_np + str2[2],...,str1[1] * hex_np + str2[5]str1[2] * hex_np + str2[1] str1[2] * hex_np + str2[2],...,str1[2] * hex_np + str2[5],{{1} },str1[3] * hex_np + str2[1],...,str1[3] * hex_np + str2[2]

如何在不使用循环的情况下执行此操作?

3 个答案:

答案 0 :(得分:3)

使用 expand.grid 获取 str1 str2 的所有组合,然后遍历行并使用您的公式:

myResult <- apply(expand.grid(str1, str2), 1, function(i)
  i[1] * hex_np + i[2])

class(myResult)
# [1] "matrix"

myResult
#       [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14] [,15]
# [1,]    6    8   10    9   11   13   12   14   16    20    22    24    22    24    26
# [2,]    8   12   16   11   15   19   14   18   22    22    26    30    24    28    32
# [3,]   10   16   22   13   19   25   16   22   28    24    30    36    26    32    38
# [4,]   12   20   28   15   23   31   18   26   34    26    34    42    28    36    44
# [5,]   14   24   34   17   27   37   20   30   40    28    38    48    30    40    50

或者我们可以使用mapply

ab <- expand.grid(str1, str2)
myResult2 <- mapply(function(a, b){a * hex_np + b}, ab[, 1], ab[, 2])
identical(myResult, myResult2)
# [1] TRUE

编辑:如果我们想要3路组合,请参阅以下内容:

myResult3 <- data.frame(expand.grid(str1, hex_np, str2))
colnames(myResult3) <- c("str1", "hex_np", "str2")

myResult3$res <- with(myResult3, str1 * hex_np + str2)

head(myResult3)
#   str1 hex_np str2 res
# 1    1      2    4   6
# 2    2      2    4   8
# 3    3      2    4  10
# 4    1      4    4   8
# 5    2      4    4  12
# 6    3      4    4  16

答案 1 :(得分:2)

设置数据

str1 = c(1, 2, 3)
str2 = c(4, 7, 10, 18, 20)
hex_np = c(2, 4, 6, 8, 10)

解决方案#1

如果您可以在三维array中使用结果,则可以尝试简单:

outer(outer(str1, hex_np), str2, "+")

解决方案#2

如果没有,我们需要以匹配所需格式的方式更改数组的尺寸。我们可以使用base::aperm来实现这一目标。

array(aperm(a = outer(outer(str1, hex_np), str2, "+"), perm = c(3,1,2)), c(15,5))

#      [,1] [,2] [,3] [,4] [,5]
# [1,]    6    8   10   12   14
# [2,]    9   11   13   15   17
# [3,]   12   14   16   18   20
# [4,]   20   22   24   26   28
# [5,]   22   24   26   28   30
# [6,]    8   12   16   20   24
# [7,]   11   15   19   23   27
# [8,]   14   18   22   26   30
# [9,]   22   26   30   34   38
#[10,]   24   28   32   36   40
#[11,]   10   16   22   28   34
#[12,]   13   19   25   31   37
#[13,]   16   22   28   34   40
#[14,]   24   30   36   42   48
#[15,]   26   32   38   44   50

微基准

为了比较所提供的解决方案,这里是microbenchmark::microbenchmark

library(microbenchmark)

str1 = c(1, 2, 3)
str2 = c(4, 7, 10, 18, 20)
hex_np = c(2, 4, 6, 8, 10)

microbenchmark(
    'catastrophic-failure' = array(aperm(a = outer(outer(str1, hex_np), str2, "+"), perm = c(3,1,2)), c(15,5)),
    zx8754_a = apply(expand.grid(str1, str2), 1, function(i) i[1] * hex_np + i[2]),
    zx8754_b = {ab <- expand.grid(str1, str2); mapply(function(a, b){a * hex_np + b}, ab[, 1], ab[, 2])},
    'Tom Wenseleers' = t(apply(expand.grid(str1=c(1, 2, 3), str2=c(4, 7, 10, 18, 20)), 1, function(r) r[1]*hex_np+r[2])),
    times = 1000L)
#Unit: microseconds
#                 expr     min      lq      mean  median       uq      max neval  cld
# catastrophic-failure  27.526  38.723  43.18418  41.989  45.7210  191.279  1000 a   
#             zx8754_a 226.268 237.932 258.80061 243.064 257.5265 2259.418  1000   c 
#             zx8754_b 167.486 188.946 210.34001 195.944 207.1410 1780.289  1000  b  
#       Tom Wenseleers 243.064 251.928 279.18529 257.993 275.2545 2764.673  1000    d

因此,对于所提供的数据,我的解决方案更快,可能是由于直接使用数组。

答案 2 :(得分:1)

要将结果作为行方式矩阵,请执行以下操作:

t(apply(expand.grid(str1=c(1, 2, 3), str2=c(4, 7, 10, 18, 20)),
        1, function(r) r[1]*hex_np+r[2]))
      [,1] [,2] [,3] [,4] [,5]
 [1,]    6    8   10   12   14
 [2,]    8   12   16   20   24
 [3,]   10   16   22   28   34
 [4,]    9   11   13   15   17
 [5,]   11   15   19   23   27
 [6,]   13   19   25   31   37
 [7,]   12   14   16   18   20
 [8,]   14   18   22   26   30
 [9,]   16   22   28   34   40
[10,]   20   22   24   26   28
[11,]   22   26   30   34   38
[12,]   24   30   36   42   48
[13,]   22   24   26   28   30
[14,]   24   28   32   36   40
[15,]   26   32   38   44   50