【问题标题】:Efficient way to obtain matrix with pairwise maximum between two values获得两个值之间成对最大值的矩阵的有效方法
【发布时间】:2019-05-31 16:30:33
【问题描述】:

我想为条目i,j 创建一个矩阵,它返回D[i,1]D[j,1] 之间的最大值。

我有一个数字向量,在 MWE 中可以简化为:

set.seed(10)
n <- 2000 
D <- matrix(runif(n,0,100), ncol=1)

Base R 中使用双 for 循环,效率极低:

X <- Matrix::Matrix(0, nrow = n, ncol = n, sparse = T)

for (i in 1:n) {
  for (j in 1:n) {
    X[i,j] <- max(D[i,1], D[j,1])
  }
}

我也试过 dplyr

library(dplyr)

X <- tibble(i = 1:n, D = D)

X <- expand.grid(i = 1:n, j = 1:n)

X <- X %>%
  as_tibble() %>%
  left_join(X, by = "i") %>%
  left_join(X, by = c("j" = "i")) %>%
  rowwise() %>%
  mutate(D = max(D.x, D.y)) %>%
  ungroup()

它在我可以做X &lt;- Matrix::Matrix(X$D, nrow = n, ncol = n, sparse = T)之前返回Error: std::bad_alloc

我最后一次尝试是使用 RcppArmadillo 以使其也适用于 Windows:

#include <RcppArmadillo.h>

// [[Rcpp::depends(RcppArmadillo)]]

using namespace Rcpp;

// [[Rcpp::export]]
arma::mat pairwise_max(arma::mat x, arma::mat y) {
  // Constants
  int n = (int) x.n_rows;

  // Output
  arma::mat z(n,n);

  // Filling with ones
  z.ones();

  for (int i=0; i<n; i++)
    for (int j=0; j<=i; j++) {
      // Fill the lower part
      z.at(i,j) = std::max(y(i,0), y(j,0));
      // Fill the upper part
      z.at(j,i) = z.at(i,j);
    }

    return z;
}

它的工作原理几乎完美无缺,但我很确定有一种我看不到的基本 R 的有效方法。

【问题讨论】:

  • 从基本 R 解决方案中删除 sparse 矩阵。这是不必要的增长矩阵。只需使用matrix(0, nrow = n, ncol = n)
  • Rcpp 解决方案将是最快的,因为这需要两个循环。

标签: r matrix dplyr rcpp


【解决方案1】:

在基础 R 中,我会这样做

D2 <- drop(D)
X2 <- outer(D2, D2, pmax)

这大约是双 for 循环的 20 倍。

【讨论】:

  • 不错!213456
猜你喜欢
  • 1970-01-01
  • 2013-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-24
  • 2019-07-28
  • 1970-01-01
相关资源
最近更新 更多