我需要创建一个函数,为我提供1:n数字的所有可能组合。函数的自变量为n。我需要在不使用R内的combn函数或任何其他预安装函数的情况下执行此操作。
上面这张照片描绘了我想做的事。底部只是使用combn来检查上述功能是否有效。
我做了以下事情,但是显然这不是当前正确的方法。
pairwise_comp <- function(n) {
res <- matrix(nrow = 0, ncol = 2)
for (i in 1:n) {
res <-rbind(res,cbind( i , i+1))
}
return(res)
}
答案 0 :(得分:3)
有几种方法可以解决这个问题,有些有效,有些可读(主观),但两种方法都不多。
例如,您可以递归进行操作,例如:
pairwise_recur <- function(n, start = 1) {
if (n == start) return()
nrows <- factorial(n) / (factorial(2) * factorial(n-2))
res <- matrix(nrow = nrows, ncol = 2)
rbind(
cbind(rep(start, times = n - start),
1 + start:(n-1)),
pairwise_recur(n, start = start + 1)
)
}
pairwise_recur(4)
# [,1] [,2]
# [1,] 1 2
# [2,] 1 3
# [3,] 1 4
# [4,] 2 3
# [5,] 2 4
# [6,] 3 4
但是与此有关的几件事效率较低:
rbind
的事情。n < start
或n==0
进行呼叫,则会失败。很有可能:
factorial
,则可以将其与prod(1:n)
混淆。下面的其余功能将使用此prod
方法,这是您的首选。factorial
和prod
都将以很高的n
开始失败,很可能超出了您将用于此分配的限制。以这些数字,可能有必要进入gamma
领域,对高n
阶乘进行更高效的计算(并且可能有必要直到R完全兼容64位整数)。 / li>
解决其中一些问题的迭代器
pairwise_iter <- function(n) {
nrows <- prod(1:n) / ( prod(1:2) * prod(1:(n-2)) )
res <- matrix(nrow = nrows, ncol = 2)
r <- 0
for (i in 1:(n-1)) {
for (j in (i+1):n) {
r <- r + 1
res[r,1] <- i
res[r,2] <- j
}
}
res
}
# same output
坦率地说,只要对r
和i
进行一些聪明的数学运算,就可以摆脱j
计数器。
但是在n < 3
时仍然容易出现问题。可以通过以下方法缓解这种情况:
pairwise_iter2 <- function(n) {
if (n <= 1) return(matrix(nrow = 0, ncol = 2))
nrows <- prod(seq_len(n)) / ( prod(1:2) * prod(seq_len(n-2)) )
res <- matrix(nrow = nrows, ncol = 2)
r <- 0
for (i in 1:(n-1)) {
for (j in (i+1):n) {
r <- r + 1
res[r,1] <- i
res[r,2] <- j
}
}
res
}
pairwise_iter2(0)
# [,1] [,2]
pairwise_iter2(1)
# [,1] [,2]
pairwise_iter2(2)
# [,1] [,2]
# [1,] 1 2
pairwise_iter2(3)
# [,1] [,2]
# [1,] 1 2
# [2,] 1 3
# [3,] 2 3
一个区别(由开头的if
/ return
减轻了)是使用seq_len
:如果要一个长度为n
的序列,则1:n
仅与n >= 1
一样准确。如果n
为0,则1:0
产生一个长度为2的向量,这不是您应该得到的;相反,seq_len(0)
返回长度为0的向量,该向量更一致。
这在R的处理方式中仍然不是“高效”的。为此,您可以删除内部for
循环并按向量进行分配:
pairwise_vec1 <- function(n) {
if (n <= 1) return(matrix(nrow = 0, ncol = 2))
nrows <- prod(seq_len(n)) / ( prod(1:2) * prod(seq_len(n-2)) )
res <- matrix(nrow = nrows, ncol = 2)
r <- 0
for (i in 1:(n-1)) {
vec <- seq_len(n - i)
res[r + vec, 1] <- i
res[r + vec, 2] <- i + vec
r <- r + length(vec)
}
res
}
实际上甚至在外部for
循环中也可能生成而没有,但是它需要更多的矢量化向导,这既超出了此任务的范围,也超出了我的时间专门用于本课。