尝试使用RcppArmadillo编写setdiff()函数会导致编译错误 我试图用C++编写一个C++中的R的StimeDeffice()函数的类比。我的方法相当粗糙: // [[Rcpp::export]] arma::uvec my_setdiff(arma::uvec x, arma::uvec y){ // Coefficientes of unsigned integer vector y form a subset of the coefficients of unsigned integer vector x. // Returns set difference between the coefficients of x and those of y int n2 = y.n_elem; uword q1; for (int j=0 ; j<n2 ; j++){ q1 = find(x==y[j]); x.shed_row(q1); } return x; } /[[Rcpp::export]] arma::uvec my_setdiff(arma::uvec x,arma::uvec y){ //无符号整数向量y的系数构成无符号整数向量x的系数的子集。 //返回x和y的系数之间的集差 int n2=y.n_元素; uwordq1; 对于(int j=0;j
问题在于,尝试使用RcppArmadillo编写setdiff()函数会导致编译错误 我试图用C++编写一个C++中的R的StimeDeffice()函数的类比。我的方法相当粗糙: // [[Rcpp::export]] arma::uvec my_setdiff(arma::uvec x, arma::uvec y){ // Coefficientes of unsigned integer vector y form a subset of the coefficients of unsigned integer vector x. // Returns set difference between the coefficients of x and those of y int n2 = y.n_elem; uword q1; for (int j=0 ; j<n2 ; j++){ q1 = find(x==y[j]); x.shed_row(q1); } return x; } /[[Rcpp::export]] arma::uvec my_setdiff(arma::uvec x,arma::uvec y){ //无符号整数向量y的系数构成无符号整数向量x的系数的子集。 //返回x和y的系数之间的集差 int n2=y.n_元素; uwordq1; 对于(int j=0;j,c++,r,rcpp,armadillo,C++,R,Rcpp,Armadillo,问题在于,arma::find返回一个uvec,并且不知道如何进行到arma::uword的隐式转换,正如@mtall所指出的。您可以使用模板化的arma::conv_to::from()来帮助编译器函数。此外,我还包括了另一个版本的my_setdiff,它返回一个Rcpp::NumericVector,因为尽管第一个版本返回正确的值,但从技术上讲它是一个矩阵(即它有维度),我假设您希望它尽可能与R的setdiff兼容。这是通过使用R\NilValue和Rcpp::attr成员函数将返回向量的d
arma::find
返回一个uvec
,并且不知道如何进行到arma::uword
的隐式转换,正如@mtall所指出的。您可以使用模板化的arma::conv_to::from()来帮助编译器
函数。此外,我还包括了另一个版本的my_setdiff
,它返回一个Rcpp::NumericVector
,因为尽管第一个版本返回正确的值,但从技术上讲它是一个矩阵(即它有维度),我假设您希望它尽可能与R的setdiff
兼容。这是通过使用R\NilValue
和Rcpp::attr
成员函数将返回向量的dim
属性设置为NULL
来实现的
如果使用非唯一元素传递向量,则以前的版本将抛出错误,例如
R> my_setdiff2(X,Y)
error: conv_to(): given object doesn't have exactly one element
为了解决这个问题并更紧密地反映R的setdiff
,我们只需要使x
和y
独一无二。此外,我用q1(0)
将arma::conv_切换到::from
(其中q1
现在是uvec
,而不是uword
),因为uvec
只是uword
s的一个向量,显式转换似乎有点不雅观。我使用了STL,从arma::uvec来回转换
#include <RcppArmadillo.h>
#include <algorithm>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::uvec std_setdiff(arma::uvec& x, arma::uvec& y) {
std::vector<int> a = arma::conv_to< std::vector<int> >::from(arma::sort(x));
std::vector<int> b = arma::conv_to< std::vector<int> >::from(arma::sort(y));
std::vector<int> out;
std::set_difference(a.begin(), a.end(), b.begin(), b.end(),
std::inserter(out, out.end()));
return arma::conv_to<arma::uvec>::from(out);
}
#包括
#包括
//[[Rcpp::depends(RcppArmadillo)]]
//[[Rcpp::导出]]
arma::uvec标准设置差异(arma::uvec&x,arma::uvec&y){
std::vector a=arma::conv_to::from(arma::sort(x));
std::vector b=arma::conv_to::from(arma::sort(y));
std::向量输出;
设置差异(a.开始(),a.结束(),b.开始(),b.结束(),
std::inserter(out,out.end());
将arma::conv_返回到::from(out);
}
编辑:我认为应该进行性能比较。当集合的相对大小顺序相反时,差异会变小
a <- sample.int(350)
b <- sample.int(150)
microbenchmark::microbenchmark(std_setdiff(a, b), arma_setdiff(a, b))
> Unit: microseconds
> expr min lq mean median uq max neval cld
> std_setdiff(a, b) 11.548 14.7545 17.29930 17.107 19.245 36.779 100 a
> arma_setdiff(a, b) 60.727 65.0040 71.77804 66.714 72.702 138.133 100 b
a表达式最小lq平均uq最大neval cld
>标准设置差异(a,b)11.54814.754517.2993017.10719.24536.779100 a
>阿马努塞迪夫(a,b)60.727 65.0040 71.77804 66.714 72.702 138.133 100 b
提问者可能已经得到了答案。但是,以下模板版本可能更通用。这相当于Matlab中的函数
如果p和Q是两个集合,那么它们的差异由p-Q或Q-p给出。如果p={1,2,3,4}
和Q={4,5,6}
,p-Q表示p中不在Q中的元素。即,在上面的示例中p-Q={1,2,3}
/* setdiff(t1, t2) is similar to setdiff() function in MATLAB. It removes the common elements and
gives the uncommon elements in the vectors t1 and t2. */
template <typename T>
T setdiff(T t1, T t2)
{
int size_of_t1 = size(t1);
int size_of_t2 = size(t2);
T Intersection_Elements;
uvec iA, iB;
intersect(Intersection_Elements, iA, iB, t1, t2);
for (int i = 0; i < size(iA); i++)
{
t1(iA(i)) = 0;
}
for (int i = 0; i < size(iB); i++)
{
t2(iB(i)) = 0;
}
T t1_t2_vec(size_of_t1 + size_of_t2);
t1_t2_vec = join_vert(t1, t2);
T DiffVec = nonzeros(t1_t2_vec);
return DiffVec;
}
/*setdiff(t1,t2)类似于MATLAB中的setdiff()函数。它删除了常用元素和
给出向量t1和t2中的不常见元素*/
模板
T setdiff(T t1,T t2)
{
int size_of_t1=大小(t1);
int size_of_t2=大小(t2);
T交叉元素;
uvecia,iB;
相交(相交元素、iA、iB、t1、t2);
对于(int i=0;i
欢迎提出任何改进算法性能的建议。shed_row()
可能不是arma::uvec
的成员函数。行q1=find(x==y[j])
是错误的。的输出总是,而不是uword。这不符合预期。例如,arma_setdiff(10:13,4:5)
为我抛出了一个错误:arma_setdiff(10:13,4:5)中的错误:Mat::operator():索引超出范围
@Johan Larsson fixed。
#include <RcppArmadillo.h>
#include <algorithm>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::uvec std_setdiff(arma::uvec& x, arma::uvec& y) {
std::vector<int> a = arma::conv_to< std::vector<int> >::from(arma::sort(x));
std::vector<int> b = arma::conv_to< std::vector<int> >::from(arma::sort(y));
std::vector<int> out;
std::set_difference(a.begin(), a.end(), b.begin(), b.end(),
std::inserter(out, out.end()));
return arma::conv_to<arma::uvec>::from(out);
}
a <- sample.int(350)
b <- sample.int(150)
microbenchmark::microbenchmark(std_setdiff(a, b), arma_setdiff(a, b))
> Unit: microseconds
> expr min lq mean median uq max neval cld
> std_setdiff(a, b) 11.548 14.7545 17.29930 17.107 19.245 36.779 100 a
> arma_setdiff(a, b) 60.727 65.0040 71.77804 66.714 72.702 138.133 100 b
/* setdiff(t1, t2) is similar to setdiff() function in MATLAB. It removes the common elements and
gives the uncommon elements in the vectors t1 and t2. */
template <typename T>
T setdiff(T t1, T t2)
{
int size_of_t1 = size(t1);
int size_of_t2 = size(t2);
T Intersection_Elements;
uvec iA, iB;
intersect(Intersection_Elements, iA, iB, t1, t2);
for (int i = 0; i < size(iA); i++)
{
t1(iA(i)) = 0;
}
for (int i = 0; i < size(iB); i++)
{
t2(iB(i)) = 0;
}
T t1_t2_vec(size_of_t1 + size_of_t2);
t1_t2_vec = join_vert(t1, t2);
T DiffVec = nonzeros(t1_t2_vec);
return DiffVec;
}