说我有数字字符串
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]
如何在不使用循环的情况下执行此操作?
答案 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)
如果您可以在三维array
中使用结果,则可以尝试简单:
outer(outer(str1, hex_np), str2, "+")
如果没有,我们需要以匹配所需格式的方式更改数组的尺寸。我们可以使用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