使用 Rcpp 查找重复项
Finding duplicates using Rcpp
我正在尝试找到一个更快的替代方法来在 R 中查找重复项。代码的目的是将矩阵传递给 Rcpp,其中包含该矩阵的行号,然后循环遍历整个矩阵以查找匹配项对于那一行。所讨论的矩阵是具有 1000 行和 250 列的逻辑矩阵。
听起来很简单,但下面的代码没有检测等效向量行。我不确定这是 equal() 函数的问题还是矩阵或向量的定义方式的问题。
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::plugins]]
#include <cstddef> // std:size_t
#include <iterator> // std:begin, std::end
#include <vector> // std::vector
#include <iostream>
#include <string>
// [[Rcpp::export]]
bool dupCheckRcpp (int nVector,
LogicalMatrix bigMatrix) {
// initialize
int i, j, nrow, ncol;
nrow = bigMatrix.nrow();
ncol = bigMatrix.ncol();
LogicalVector vec(ncol); // holds vector of interest
LogicalVector vecMatrix(ncol); // temp vector for loop through bigMatrix
nVector = nVector - 1;
// copy bigMatrix data into vec based on nVector row
for ( j = 0; j < ncol; ++j ) {
vec(j) = bigMatrix(nVector,j);
}
// check loop: check vecTeam against each row in allMatrix
for (i = 0; i < nrow; ++i) {
// copy bigMatrix data into vecMatrix
for ( j = 0; j < ncol; ++j ) {
vecMatrix(j) = bigMatrix(i,j);
}
// check for equality
if (i != nVector) { // skip if nVector row
// compare vecTeam to vecMatrix
if (std::equal(vec.begin(),vec.end(),vecMatrix.begin())) {
return true;
}
}
} // close check loop
return false;
}
我不太确定你的代码哪里出了问题,但请注意,你真的不应该像这样在 Rcpp 类型之间手动复制元素:
// copy bigMatrix data into vec based on nVector row
for (j = 0; j < ncol; ++j) {
vec(j) = bigMatrix(nVector, j);
}
几乎总会有合适的 class 和/或适当的赋值运算符等,让您可以更简洁、更安全地完成此操作(即不太容易出现编程错误)。这是一个更简单的实现:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
bool is_duplicate_row(R_xlen_t r, LogicalMatrix x) {
R_xlen_t i = 0, nr = x.nrow();
const LogicalMatrix::Row& y = x.row(r);
for (; i < r; i++) {
if (is_true(all(y == x.row(i)))) {
return true;
}
}
for (i = r + 1; i < nr; i++) {
if (is_true(all(y == x.row(i)))) {
return true;
}
}
return false;
}
本着我上面建议的精神,
const LogicalMatrix::Row& y = x.row(r);
为我们提供了对矩阵 的第 r
行的常量引用
x.row(i)
指的是x
的第i
行
这两个表达式都避免了 element-wise 通过 for
循环进行复制,并且在我看来更具可读性。此外,虽然使用 std::equal
或任何其他标准算法肯定没有错,但使用 is_true(all(y == x.row(i)))
等 Rcpp 糖表达式通常可以进一步简化您的代码。
set.seed(123)
m <- matrix(rbinom(1000 * 250, 1, 0.25) > 0, 1000)
m[600,] <- m[2,]
which(sapply(1:nrow(m) - 1, is_duplicate_row, m))
# [1] 2 600
c(which(duplicated(m, fromLast = TRUE)), which(duplicated(m)))
# [1] 2 600
我正在尝试找到一个更快的替代方法来在 R 中查找重复项。代码的目的是将矩阵传递给 Rcpp,其中包含该矩阵的行号,然后循环遍历整个矩阵以查找匹配项对于那一行。所讨论的矩阵是具有 1000 行和 250 列的逻辑矩阵。
听起来很简单,但下面的代码没有检测等效向量行。我不确定这是 equal() 函数的问题还是矩阵或向量的定义方式的问题。
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::plugins]]
#include <cstddef> // std:size_t
#include <iterator> // std:begin, std::end
#include <vector> // std::vector
#include <iostream>
#include <string>
// [[Rcpp::export]]
bool dupCheckRcpp (int nVector,
LogicalMatrix bigMatrix) {
// initialize
int i, j, nrow, ncol;
nrow = bigMatrix.nrow();
ncol = bigMatrix.ncol();
LogicalVector vec(ncol); // holds vector of interest
LogicalVector vecMatrix(ncol); // temp vector for loop through bigMatrix
nVector = nVector - 1;
// copy bigMatrix data into vec based on nVector row
for ( j = 0; j < ncol; ++j ) {
vec(j) = bigMatrix(nVector,j);
}
// check loop: check vecTeam against each row in allMatrix
for (i = 0; i < nrow; ++i) {
// copy bigMatrix data into vecMatrix
for ( j = 0; j < ncol; ++j ) {
vecMatrix(j) = bigMatrix(i,j);
}
// check for equality
if (i != nVector) { // skip if nVector row
// compare vecTeam to vecMatrix
if (std::equal(vec.begin(),vec.end(),vecMatrix.begin())) {
return true;
}
}
} // close check loop
return false;
}
我不太确定你的代码哪里出了问题,但请注意,你真的不应该像这样在 Rcpp 类型之间手动复制元素:
// copy bigMatrix data into vec based on nVector row
for (j = 0; j < ncol; ++j) {
vec(j) = bigMatrix(nVector, j);
}
几乎总会有合适的 class 和/或适当的赋值运算符等,让您可以更简洁、更安全地完成此操作(即不太容易出现编程错误)。这是一个更简单的实现:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
bool is_duplicate_row(R_xlen_t r, LogicalMatrix x) {
R_xlen_t i = 0, nr = x.nrow();
const LogicalMatrix::Row& y = x.row(r);
for (; i < r; i++) {
if (is_true(all(y == x.row(i)))) {
return true;
}
}
for (i = r + 1; i < nr; i++) {
if (is_true(all(y == x.row(i)))) {
return true;
}
}
return false;
}
本着我上面建议的精神,
const LogicalMatrix::Row& y = x.row(r);
为我们提供了对矩阵 的第 x.row(i)
指的是x
的第
r
行的常量引用
i
行
这两个表达式都避免了 element-wise 通过 for
循环进行复制,并且在我看来更具可读性。此外,虽然使用 std::equal
或任何其他标准算法肯定没有错,但使用 is_true(all(y == x.row(i)))
等 Rcpp 糖表达式通常可以进一步简化您的代码。
set.seed(123)
m <- matrix(rbinom(1000 * 250, 1, 0.25) > 0, 1000)
m[600,] <- m[2,]
which(sapply(1:nrow(m) - 1, is_duplicate_row, m))
# [1] 2 600
c(which(duplicated(m, fromLast = TRUE)), which(duplicated(m)))
# [1] 2 600