r - 向量元素的所有组合之间的乘积

标签 r vector combinations multiplication

假设我有一个向量 c(1, 2, 3, 4)没有重复的值。我需要一个矢量 c(1 * 2, 1 * 3, 1 * 4, 2 * 3, 2 * 4, 3 * 4) ,因此乘法是在此向量值的所有可能组合中完成的。有没有办法做到这一点?提前致谢!

最佳答案

这已经足够有趣了。我以为combn(1:4, 2, "*")将是最简单的解决方案,但它实际上不起作用。我们必须使用 combn(1:4, 2, prod) as Onyambu commented .问题是:在“N 选择 K”设置中,FUN必须能够将长度为 K 的向量作为输入。 "*"不是正确的。

## K = 2 case
"*"(c(1, 2))  ## this is different from: "*"(1, 2)
#Error in *c(1, 2) : invalid unary operator

prod(c(1, 2))
#[1] 2

我们走得太远了,但我们迟早会遇到这个
感谢 Maurits Evers详细说明 outer/lower.tri/upper.tri .这是一种避免从 outer 生成这些临时矩阵的适应方法。和 *****.tri :
tri_ind <- function (n, lower= TRUE, diag = FALSE) {
  if (diag) {
    tmp <- n:1
    j <- rep.int(1:n, tmp)
    i <- sequence(tmp) - 1L + j
    } else {
    tmp <- (n-1):1
    j <- rep.int(1:(n-1), tmp)
    i <- sequence(tmp) + j
    }
  if (lower) list(i = i, j = j)
  else list(i = j, j = i)
  }

vec <- 1:4
ind <- tri_ind(length(vec), FALSE, FALSE)
#$i
#[1] 1 1 1 2 2 3
#
#$j
#[1] 2 3 4 3 4 4

vec[ind[[1]]] * vec[ind[[2]]]
#[1]  2  3  4  6  8 12
tri_ind函数是 my this answer 的包装器.它可以用作 combn(length(vec), 2) 的快速且节省内存的替代方案或其 outer -等价。
原来我链接了一个 finv 函数,但它不适合基准测试,因为它旨在从“dist”对象(折叠的下三角矩阵)中提取一些元素。如果三角矩阵的所有元素都被引用,它的索引计算实际上会带来不必要的开销。 tri_ind是更好的选择。
library(bench)
基准指数生成
bench1 <- function (n) {
  bench::mark("combn" = combn(n, 2),
              "tri_ind" = tri_ind(n, TRUE, FALSE),
              "upper.tri" = which(upper.tri(matrix(0, n, n)), arr.ind = TRUE),
              check = FALSE)
  }

## for small problem, `tri_ind` is already the fastest
bench1(100)
#  expression      min     mean  median      max `itr/sec` mem_alloc  n_gc n_itr
#  <chr>      <bch:tm> <bch:tm> <bch:t> <bch:tm>     <dbl> <bch:byt> <dbl> <int>
#1 combn        11.6ms   11.9ms  11.9ms  12.59ms      83.7    39.1KB     9    32
#2 tri_ind     189.3µs  205.9µs 194.6µs   4.82ms    4856.     60.4KB    21  1888
#3 upper.tri   618.4µs  635.8µs 624.1µs 968.36µs    1573.    411.7KB    57   584

## `tri_ind` is 10x faster than `upper.tri`, and 100x faster than `combn`
bench1(5000)
#  expression      min     mean   median      max `itr/sec` mem_alloc  n_gc
#  <chr>      <bch:tm> <bch:tm> <bch:tm> <bch:tm>     <dbl> <bch:byt> <dbl>
#1 combn         30.6s    30.6s    30.6s    30.6s    0.0327    95.4MB   242
#2 tri_ind    231.98ms 259.31ms 259.31ms 286.63ms    3.86     143.3MB     0
#3 upper.tri     3.02s    3.02s    3.02s    3.02s    0.332    953.6MB     4
OP 问题的基准测试
bench2 <- function (n) {
  vec <- numeric(n)
  bench::mark("combn" = combn(vec, 2, prod),
              "tri_ind" = {ind <- tri_ind(n, FALSE, FALSE);
                           vec[ind[[1]]] * vec[ind[[2]]]},
              "upper.tri" = {m <- outer(vec, vec);                                
                             c(m[upper.tri(m)])},
              check = FALSE)
  }

bench2(100)
#  expression      min     mean  median      max `itr/sec` mem_alloc  n_gc n_itr
#  <chr>      <bch:tm> <bch:tm> <bch:t> <bch:tm>     <dbl> <bch:byt> <dbl> <int>
#1 combn        18.6ms   19.2ms  19.1ms  20.55ms      52.2    38.7KB     4    22
#2 tri_ind     386.9µs  432.3µs 395.6µs   7.58ms    2313.    176.6KB     1  1135
#3 upper.tri   326.9µs  488.5µs 517.6µs 699.07µs    2047.      336KB     0  1024

bench2(5000)
#  expression      min     mean   median     max `itr/sec` mem_alloc  n_gc n_itr
#  <chr>      <bch:tm> <bch:tm> <bch:tm> <bch:t>     <dbl> <bch:byt> <dbl> <int>
#1 combn        48.13s   48.13s   48.13s  48.13s    0.0208    95.3MB   204     1
#2 tri_ind     861.7ms  861.7ms  861.7ms 861.7ms    1.16     429.3MB     0     1
#3 upper.tri     1.95s    1.95s    1.95s   1.95s    0.514    810.6MB     3     1
对我来说,知道 combn 很有趣。不是用编译代码编写的。它实际上有一个 R 级别的 for 循环。各种替代方案只是试图在“N 选择 2”的情况下加速它而不编写编译代码。
更好的选择??
功能 combinations来自 gtools包使用递归算法,这对于大问题规模是有问题的。功能 combn来自 combinat包不使用编译代码,所以它并不比 combn 好来自 R 核心。 RcppAlgos包裹来自 Joseph Wood有一个 comboGenearl迄今为止我看到的最快的函数。
library(RcppAlgos)

## index generation
bench3 <- function (n) {
  bench::mark("tri_ind" = tri_ind(n, FALSE, FALSE),
              "Joseph" = comboGeneral(n, 2), check = FALSE)
  }

bench3(5000)
#  expression      min     mean   median     max `itr/sec` mem_alloc  n_gc n_itr
#  <chr>      <bch:tm> <bch:tm> <bch:tm> <bch:t>     <dbl> <bch:byt> <dbl> <int>
#1 tri_ind       290ms    297ms    297ms   303ms      3.37   143.4MB     4     2
#2 Joseph        134ms    155ms    136ms   212ms      6.46    95.4MB     2     4

## on OP's problem
bench4 <- function (n) {
  vec <- numeric(n)
  bench::mark("tri_ind" = {ind <- tri_ind(n, FALSE, FALSE);
                           vec[ind[[1]]] * vec[ind[[2]]]},
              "Joseph" = comboGeneral(vec, 2, constraintFun = "prod", keepResults = TRUE),
              check = FALSE)
  }

bench4(5000)
#  expression      min     mean   median     max `itr/sec` mem_alloc  n_gc n_itr
#  <chr>      <bch:tm> <bch:tm> <bch:tm> <bch:t>     <dbl> <bch:byt> <dbl> <int>
#1 tri_ind       956ms    956ms    956ms   956ms      1.05     429MB     3     1
#2 Joseph        361ms    362ms    362ms   363ms      2.76     286MB     1     2

约瑟夫伍德对组合/排列有各种答案。例如:Faster version of combn .

关于r - 向量元素的所有组合之间的乘积,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52086098/

相关文章:

缺少类别的 R 包插入符号混淆矩阵

r - 如何使用来自 R 中其他列的值格式化字符串

r - 如何获取带有城市名称的系统时区?

c++ - 计算 std::vector<bool> 中的设置值

c++ - 继承 vector/数组/列表并更改其大小

c++ - 如何知道 vector 的正确最大大小?最大大小()?但不是

r - 扩展 data.table 时出现奇怪的错误

python - Itertools 组合查找组合是否可整除

algorithm - 生成一个所有可能结果的矩阵,用于 throw n 个骰子(忽略顺序)

python - 查找对(连接)的组合