2016-08-11 2 views
1

Я использую arma::find_unique, и я думал, что он вернул индекс первого вхождения каждого уникального значения в вектор, но, похоже, возвращает что-то еще.Как arma :: find_unique определяет уникальные индексы?

Вот это игрушка функция:

// [[Rcpp::export]] 
arma::uvec test(arma::vec& x_) { 
    vec x=arma::sort(x_); 
    return arma::find_unique(x); 
} 

Если я запускаю функцию в R с помощью простого вектора test(5:1) я получаю вектор всех индексов 0,1,2,3,4 который имеет смысл, поскольку каждое значение является уникальным.

Если я пытаюсь что-то вроде:

set.seed(1991) 
var=sample(1:8,20,TRUE) 
test(var) 

ВЫХОДНОЙ:

1,3,6,7,19,12,14,18.

Все эти значения имеют смысл, кроме первого. Почему первое уникальное значение в индексе 1, а не 0? Ясно, что я не понимаю, что такое arma::find_unique намеревается сделать так, я был бы признателен, если бы кто-нибудь мог просветить меня.

EDIT Моя сессия информация

sessionInfo()

ответ

2

Хорошо, следующий любезно @nrussell, человек удивительно, и был дан в комментариях к «ответу». (Я не заслуживаю пометку ни upvotes.)

На самом деле, я уверен, что все это просто неправильная интерпретация документации Armadillo, которая фактически никогда не гарантирует, что используется стабильный сорт, а @Carl ожидал. Underneath, std :: sort - being called, что не гарантирует стабильный вид по стандарту C++; также заявил here:

«Порядок равных элементов не гарантируется быть сохранена.»

Я могу продемонстрировать это here, тиражирование "packet" structure использования в алгоритме броненосца. Я предполагаю, что libc++ (обычно используется OS X) реализует std::sort как стабильный вид, а libstdc++ - нет.

My turn: стабильный сортировка или поддержание относительного порядка записей с равными ключами (то есть значения) является ключевым вопросом, стоящим за этим вопросом. Например, рассмотрим следующее:

dog car pool dig 

Сортировка по первой букве с стабильной рода дает нам:

car dog dig pool 

Потому что слово «собака» появилась перед «копать» в векторе , поэтому он должен появиться перед «выкапыванием» на выходе.

Сортировка по первой букве с нестабильным рода дает нам:

car dig dog pool 

или

car dog dig pool 

Принципиальное имеет отношение к числам, так как каждый ключ генерировать буквально присутствует в другом месте. Итак, мы имеем:

2, 3, 2, 4 

Таким образом, когда уникальные значения найдены:

2, 3, 4 

2-может принимать идентификатор либо 0 или 2.

Как @nrussell объяснил, MacOS, так как ОС X Mavericks (10.9) полагается по умолчанию на --stdlib=libc++ по сравнению с традиционным флагом --stdlib=libstdc++ для компиляции. Вероятно, это была причина, по которой я не смог ее воспроизвести, так как одна реализация выбирает стабильность, а другая - нет.

Оригинал ответа

Во-первых, я не в состоянии воспроизвести это на MacOS ... (См конец)

Кажется, как будто мы можем Репрографический это на Linux, хотя (@nrussel) , Это означает, что в какой-то момент в связанном коде есть проблема.

Во-вторых, arma::find_unique реализован here с использованием matrix ops с op_find_unique. Позже это ключ, поскольку он реализует компараторы.

Таким образом, короче говоря, не должно быть никакого способа, который возможен, если вы сортируете вектор, и первый элемент всегда считается уникальным.

Функция тестирования

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

// [[Rcpp::export]] 
arma::uvec test(arma::vec& x_) { 
    Rcpp::Rcout << "Input:" << x_.t() << std::endl; 
    arma::vec x = arma::sort(x_); 
    Rcpp::Rcout << "Sorted:" << x.t() << std::endl; 
    arma::uvec o = arma::find_unique(x); 
    Rcpp::Rcout << "Indices:" << o.t() << std::endl; 
    return o; 
} 

/*** R 
set.seed(1991) 
(v=sample(1:8,20,TRUE)) 
## [1] 2 2 1 5 7 6 7 6 4 1 5 3 1 4 4 2 8 7 7 8 
sort(v) 
## [1] 1 1 1 2 2 2 3 4 4 4 5 5 6 6 7 7 7 7 8 8 

test(v) 
### Received 
## 2.0000 2.0000 1.0000 5.0000 7.0000 6.0000 7.0000 6.0000 4.0000 1.0000 5.0000 3.0000 1.0000 4.0000 4.0000 2.0000 8.0000 7.0000 7.0000 8.0000 

### Sorted 
## 1.0000 1.0000 1.0000 2.0000 2.0000 2.0000 3.0000 4.0000 4.0000 4.0000 5.0000 5.0000 6.0000 6.0000 7.0000 7.0000 7.0000 7.0000 8.0000 8.0000 

### Output 
## 0 3 6 7 10 12 14 18 
*/ 
+0

Благодаря @Coatless. Я так же отлаживал «Rcout». Я использую Windows, и я клянусь, что получаю 1, а не 0 – Carl

+0

@Carl, запустите вышеуказанный кусок кода. Опубликуйте снимок экрана о результатах. – coatless

+0

без проблем дайте мне несколько – Carl

Смежные вопросы