在arma :: mat中查找唯一的行

cry*_*nic 1 r unique armadillo rcpp

在R中,我们可以使用唯一方法来查找唯一行

> data <- matrix(c(1,1,0,1,1,1,0,1),ncol = 2)
> data
     [,1] [,2]
[1,]    1    1
[2,]    1    1
[3,]    0    0
[4,]    1    1

> unique(data)
     [,1] [,2]
[1,]    1    1
[2,]    0    0
Run Code Online (Sandbox Code Playgroud)

我们怎样才能arma::mat在Rcpp中做到这一点?这里唯一函数返回唯一元素而不是唯一行.

nru*_*ell 6

我认为在Armadillo库中没有内置的方法可以做到这一点,但这里有一个简单的方法:

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

template <typename T>
inline bool rows_equal(const T& lhs, const T& rhs, double tol = 0.00000001) {
    return arma::approx_equal(lhs, rhs, "absdiff", tol);
}

// [[Rcpp::export]]
arma::mat unique_rows(const arma::mat& x) {
    unsigned int count = 1, i = 1, j = 1, nr = x.n_rows, nc = x.n_cols;
    arma::mat result(nr, nc);
    result.row(0) = x.row(0);

    for ( ; i < nr; i++) {
        bool matched = false;
        if (rows_equal(x.row(i), result.row(0))) continue;

        for (j = i + 1; j < nr; j++) {
            if (rows_equal(x.row(i), x.row(j))) {
                matched = true;
                break;
            }
        }

        if (!matched) result.row(count++) = x.row(i);
    }

    return result.rows(0, count - 1);
}

/*** R

data <- matrix(c(1,1,0,1,1,1,0,1), ncol = 2)
all.equal(unique(data), unique_rows(data))
#[1] TRUE

data2 <- matrix(1:9, nrow = 3)
all.equal(unique(data2), unique_rows(data2))
#[1] TRUE

data3 <- matrix(0, nrow = 3, ncol = 3)
all.equal(unique(data3), unique_rows(data3))
#[1] TRUE

data4 <- matrix(c(0, 0, 0, 1, 1, 0, 1, 1), ncol = 2)
all.equal(unique(data4), unique_rows(data4))
#[1] TRUE

*/
Run Code Online (Sandbox Code Playgroud)

正如意见建议的mtall,rows_equal使用arma::approx_equal测试相等,而不是operator==,避免了一些固有的浮点数的比较问题.该功能中使用的选项有些随意选择,当然可以根据需要进行更改; 但是它的值tol大致等于R使用的默认容差all.equal,即.Machine$double.eps^0.5(0.00000001490116在我的机器上).