我正在努力处理arma :: mat类矩阵的子集列。
假设给出了arma::mat X
,并且我尝试创建索引向量IDX
,以便进行X.cols(IDX)
。特别地,索引向量具有从1到p(X
的维数)的第k个整数。例如,可能对每个偶数列IDX=[2,4,6,8, ...]
都感兴趣。
基于this documentation,如果m <= p,则可以使用X.cols(0, m - 1)
轻松提取诸如[0,1,2,...,m-1]的连续索引。但是,我找不到用上述索引向量IDX
子集矩阵的好方法。
我想知道如何完成此代码以提供所需的输出。
我的“ subset_armamat.cpp”文件看起来像
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
using namespace Rcpp;
using namespace arma;
// [[Rcpp::export]]
mat subset_armamat(mat X, int k){
uvec IDX = "every k-th integer from 0 to X.ncols";
return X.cols(IDX);
}
执行所定义函数的R代码是
library("Rcpp")
sourceCpp("subset_armamat.cpp")
subset_armamat(matrix(1:10, 2, 5, byrow = T), 2)
这将产生一个2 x 3矩阵,如以下R代码所给出的
> matrix(1:10, 2, 5, byrow = T)[,seq(1, 5, by = 2)]
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 6 8 10
如果您提供任何输入,将不胜感激。
p.s。我试图
seq(1,m) * 2
,但这不适用于X.cols()
。 find(seq(1,p) % 2 == 0)
查找索引,但是%
运算符在seq(1,p)
和2
之间不能很好地工作。 答案 0 :(得分:4)
F. Privé's answer表明,实际上,您可以使用s
使用uvec
来对矩阵进行子集化,即使它不是连续的范围,也可以使用基数R .cols()
函数生成序列。我将进一步说明,您可以使用Armadillo函数生成序列。您可以使用seq()
-它“生成具有规则间隔元素的向量”(Armadillo documentation source):
arma::regspace()
与调用R的// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
using namespace Rcpp;
using namespace arma;
// [[Rcpp::export]]
mat subset_armamat(mat X, int k) {
uvec IDX = regspace<uvec>(0, k, X.n_cols-1);
return X.cols(IDX);
}
(其中seq()
是F.Privé的答案中的函数)的比较:
subset_armamatR()
由reprex package(v0.2.1)于2018-10-17创建
来自hbrerkere的评论值得进行一些简短的额外讨论。如果从C ++调用此函数,则可以通过将library("Rcpp")
sourceCpp("subset_armamat.cpp")
mat <- matrix(1:10, 2, 5, byrow = TRUE)
subset_armamat(mat, 2)
#> [,1] [,2] [,3]
#> [1,] 1 3 5
#> [2,] 6 8 10
subset_armamatR(mat, 2)
#> [,1] [,2] [,3]
#> [1,] 1 3 5
#> [2,] 6 8 10
library(microbenchmark)
microbenchmark(Rseq = subset_armamatR(mat, 2),
regspace = subset_armamat(mat, 2))
#> Unit: microseconds
#> expr min lq mean median uq max neval cld
#> Rseq 235.535 239.1615 291.1954 241.9850 248.6005 4704.467 100 a
#> regspace 14.221 15.0225 520.9235 15.8165 16.6740 50408.375 100 a
更改为mat subset_armamat(mat X, int k)
来提高速度。这样通过引用传递可避免不必要的复制,并且当您不打算更改通过引用传递的对象时,应使用mat subset_armamat(const mat& X, int k)
。但是,如果您是从R调用此函数,则无法避免复制,因为const
不是本机R类型(例如,参见this answer的Dirk Eddelbuettel(两者的维护者) Rcpp
和RcppArmadillo
)。请考虑以下示例:
arma::mat
然后从R呼叫:
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
// [[Rcpp::export]]
void reference_example(arma::mat& X) {
X(0, 0) = 42;
}
// [[Rcpp::export]]
void print_reference_example(arma::mat X) {
reference_example(X);
Rcpp::Rcout << X << "\n";
}
由reprex package(v0.2.1)于2018-10-18创建
答案 1 :(得分:2)
这有效:
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
using namespace Rcpp;
using namespace arma;
// [[Rcpp::export]]
mat subset_armamat(mat X, int k) {
// Obtain environment containing function
Rcpp::Environment base("package:base");
// Make function callable from C++
Rcpp::Function seq = base["seq"];
uvec IDX = as<uvec>(seq(0, X.n_cols, k));
return X.cols(IDX);
}
我只是从Rcpp调用R函数base::seq()
。