【问题标题】:How to replace elements of a matrix in C++ with values from another matrix (using Rcpp)?如何用另一个矩阵的值替换 C++ 中的矩阵元素(使用 Rcpp)?
【发布时间】:2015-12-08 16:55:01
【问题描述】:

我有一个使用 Rcpp 的小型 C++ 函数,它将一个矩阵的元素替换为另一个矩阵的值。它适用于单个单元格或如下列:

cppFunction('NumericMatrix changeC(NumericMatrix one, NumericMatrix two) {
NumericMatrix a = one;
NumericMatrix b = two;
b(_,1) = a(_,1);
return b;
}')

changeC(g,f)

如果原来f是下面的矩阵:

      [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    6    6    6    6    6    6
[2,]    6    6    6    6    6    6
[3,]    6    6    6    6    6    6
[4,]    6    6    6    6    6    6
[5,]    6    6    6    6    6    6
[6,]    6    6    6    6    6    6

和 g 看起来像下面的矩阵:

        [,1] [,2] [,3] [,4] [,5] [,6]
 [1,]    5    5    5    5    5    5
 [2,]    5    5    5    5    5    5
 [3,]    5    5    5    5    5    5
 [4,]    5    5    5    5    5    5
 [5,]    5    5    5    5    5    5
 [6,]    5    5    5    5    5    5

当我运行 changeC(g,f) 时,我最终得到(如预期的那样):

      [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    6    5    6    6    6    6
[2,]    6    5    6    6    6    6
[3,]    6    5    6    6    6    6
[4,]    6    5    6    6    6    6
[5,]    6    5    6    6    6    6
[6,]    6    5    6    6    6    6

但我真正想做的是将一个矩阵的子集替换为来自不同位置的另一个矩阵的子集(例如,一个矩阵 (3*3) 的第 1 到 3 行、第 1 到 3 列到第 3 行到6,其他矩阵的第 3 到 6 列(也是 3*3)。我试过了:

cppFunction('NumericMatrix changeC(NumericMatrix one, NumericMatrix two) {
NumericMatrix a = one;
NumericMatrix b = two;
b( Range(0,2), Range(0,2)) = a( Range(3,5), Range(3,5));
return b;
}')

但这不会编译。虽然:

cppFunction('NumericMatrix changeC(NumericMatrix one, NumericMatrix two) {
NumericMatrix a = one;
NumericMatrix b = two;
b = a( Range(3,5), Range(3,5));
return b;
}')

编译。我究竟做错了什么?在 R 中,我会执行以下操作:

f[1:3,1:3]

提前感谢您的帮助。

编辑 1

在玩了一会儿之后,我设法让我的矩阵向东和向西移动(我认为它类似于向北和向南 - 可能是东北、西北的两步方法??):

func <- 'NumericMatrix eastC(NumericMatrix a) {
int acoln=a.ncol();
NumericMatrix out(a.nrow(),a.ncol()) ;
for (int j = 0;j < acoln;j++) {
if (j > 0) {
out(_,j) = a(_,j-1);
 } else {
  out(_,j) = a(_,0);
 }
 }
 return out ;
 }'
 cppFunction(func)

欢迎任何改进。理想情况下,我希望将第一列保留为零而不是第 0 列。有什么想法吗?

【问题讨论】:

  • 如果你用几个嵌套的 for 循环来做这件事会发生什么?
  • 你能演示一下吗 - 我对 C++ 很陌生?
  • 在从 R 迁移到 C++ 时,您必须执行许多 R 本身会执行的步骤。 IE-R 是矢量化的,C++ 不是。正如 42 条注释,通过两个循环(行、列)执行此操作是一种选择。另一种选择是在 RcppEigen 中使用 block operations
  • 另外,您应该通过引用传递并在不变的矩阵上使用const(在您的第一个示例中为one)
  • Alex,42 岁,我非常想了解您在说什么,但不知道该怎么做。请您发布答案吗?

标签: c++ r matrix rcpp


【解决方案1】:

我不认为 Rcpp subMatrix 允许以这种方式分配。

看看使用 RcppArmadillo 和Armadillo submatrix views

#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]

using namespace arma;

// [[Rcpp::export]]
mat example( mat m1, mat m2) {
  m1.submat( 0,0, 2,2) = m2.submat( 3,3, 5,5 );
  return m1;
}

/*** R
m1 <- matrix(1,6,6)
m2 <- matrix(-1,6,6)
example(m1, m2)
*/

> m1 <- matrix(1,6,6)

> m2 <- matrix(-1,6,6)

> example(m1, m2)
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]   -1   -1   -1    1    1    1
[2,]   -1   -1   -1    1    1    1
[3,]   -1   -1   -1    1    1    1
[4,]    1    1    1    1    1    1
[5,]    1    1    1    1    1    1
[6,]    1    1    1    1    1    1

【讨论】:

  • 我想试试 RcppArmadillo - 但是你在哪里写这段代码?在 R?或者在另一个编辑器中编译它?当我尝试在 R 中编写此代码时,我得到的只是错误 - 正如您所知,我没有使用 Armadillo 的经验。我上面的 C++ 代码是在 R 中编写和编译的。
  • 创建一个test.cpp 文件,并使用'sourceCpp("test.cpp")`,它是你的Rcpp包的一部分。另外,请阅读 Rcpp 小插曲。 :)
  • 我有 - 徒劳。感谢您的指点 - 试过了 - 现在明白了。非常感谢 - 我整天都在为如何阅读这种类型的代码而苦苦挣扎。
  • 使用犰狳绝对有潜力,现在我可以使用它了——我认为它不会比我上面的代码快很多,但肯定有更多的控制权。
  • 我应该更快,正如 Alex 在 cmets 中所说的那样;使用按引用传递(不要忘记 const)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-10
  • 2013-03-14
  • 1970-01-01
  • 2016-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多