Я не думаю, что в библиотеке 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
*/
Как было предложено mtall в комментариях, rows_equal
использует arma::approx_equal
для проверки равенства, а не operator==
, чтобы избежать некоторых проблем сравнения, присущих числам с плавающей запятой. Параметры, используемые в этой функции, были выбраны несколько произвольно и, конечно, могут быть изменены по мере необходимости; но значение tol
примерно равно допуску по умолчанию, используемому R all.equal
, который равен .Machine$double.eps^0.5
(~ 0.00000001490116
на моей машине).
person
nrussell
schedule
10.05.2016