arma::find_unique 如何确定唯一索引?
How does arma::find_unique determine unique indices?
我正在使用 arma::find_unique
,我认为它 return 编辑了向量中每个唯一值第一次出现的索引,但它似乎 return 其他东西。
这是一个玩具函数:
// [[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
的意图,所以如果有人能启发我,我将不胜感激。
编辑
我的会话信息
好的,以下是@nrussell 提供的,这个人很了不起,并且在评论中给出了这个“答案”。 (我不值得打勾,也不值得点赞。)
Actually, I'm pretty sure this is all just a misinterpretation of the Armadillo documentation, which never actually guarantees that a stable sort is used, as @Carl was expecting. Underneath, std::sort is being called
, which is not guaranteed to be a stable sort by the C++ standard; also stated here:
"The order of equal elements is not guaranteed to be preserved."
我可以演示此 here, replicating the "packet" structure 在犰狳算法中的使用。我的猜测是 libc++
(通常由 OS X 使用)确实实现了 std::sort
作为稳定排序,而 libstdc++
没有。
轮到我了:稳定排序,或维护具有相同键(即值)的记录的相对顺序,是这个问题背后的关键问题。例如,考虑以下内容:
dog car pool dig
按 稳定 排序的第一个字母排序得到:
car dog dig pool
因为单词“dog”在向量中出现在“dig”之前,因此在输出中它必须出现在“dig”之前。
按 不稳定 排序的第一个字母排序得到:
car dig dog pool
或
car dog dig pool
主体与数字相关,因为每个生成的密钥实际上都存在于其他地方。所以,我们有:
2, 3, 2, 4
因此,当找到唯一值时:
2, 3, 4
2 的 id 可以是 0 或 2。
正如@nrussell 所解释的那样,macOS 自 OS X Mavericks (10.9) 默认依赖于 --stdlib=libc++
而不是传统的 --stdlib=libstdc++
编译标志。这可能是我无法复制它的原因,因为一种实现选择了稳定性而另一种则没有。
原答案
首先,我无法在 mac 上复制它OS...(见末)
虽然 (@nrussel),但我们似乎能够在 Linux 上重现这一点。这意味着在某些时候,链接代码中存在问题。
其次,arma::find_unique is implemented here using matrix ops with 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
*/
我正在使用 arma::find_unique
,我认为它 return 编辑了向量中每个唯一值第一次出现的索引,但它似乎 return 其他东西。
这是一个玩具函数:
// [[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
的意图,所以如果有人能启发我,我将不胜感激。
编辑 我的会话信息
好的,以下是@nrussell 提供的,这个人很了不起,并且在评论中给出了这个“答案”。 (我不值得打勾,也不值得点赞。)
Actually, I'm pretty sure this is all just a misinterpretation of the Armadillo documentation, which never actually guarantees that a stable sort is used, as @Carl was expecting. Underneath, std::sort is
being called
, which is not guaranteed to be a stable sort by the C++ standard; also stated here:"The order of equal elements is not guaranteed to be preserved."
我可以演示此 here, replicating the "packet" structure 在犰狳算法中的使用。我的猜测是
libc++
(通常由 OS X 使用)确实实现了std::sort
作为稳定排序,而libstdc++
没有。
轮到我了:稳定排序,或维护具有相同键(即值)的记录的相对顺序,是这个问题背后的关键问题。例如,考虑以下内容:
dog car pool dig
按 稳定 排序的第一个字母排序得到:
car dog dig pool
因为单词“dog”在向量中出现在“dig”之前,因此在输出中它必须出现在“dig”之前。
按 不稳定 排序的第一个字母排序得到:
car dig dog pool
或
car dog dig pool
主体与数字相关,因为每个生成的密钥实际上都存在于其他地方。所以,我们有:
2, 3, 2, 4
因此,当找到唯一值时:
2, 3, 4
2 的 id 可以是 0 或 2。
正如@nrussell 所解释的那样,macOS 自 OS X Mavericks (10.9) 默认依赖于 --stdlib=libc++
而不是传统的 --stdlib=libstdc++
编译标志。这可能是我无法复制它的原因,因为一种实现选择了稳定性而另一种则没有。
原答案
首先,我无法在 mac 上复制它OS...(见末)
虽然 (@nrussel),但我们似乎能够在 Linux 上重现这一点。这意味着在某些时候,链接代码中存在问题。
其次,arma::find_unique is implemented here using matrix ops with 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
*/