C++ Armadillo:获取向量中元素的等级

C++ Armadillo: Get the ranks of the elements in a vector

假设我有一个向量,我想获取元素排序后的排名。

所以如果我有向量:

0.5
1.5
3.5
0.1

我需要返回每个元素的行列:

2
3
4
1

有没有办法在犰狳中做到这一点?这与之前的 post 不同,因为我们在排序之前获得排名而不是索引。

在这里,检查一下:

#include<iostream>
#include<vector> // std:: vector
#include <algorithm> // std::sort
#include <map> // std::map

using namespace std;


int main() {
    vector<double> myVector = { 0.5, 1.5, 3.5, 0.1 };
    vector<double> Sorted = myVector;

    std::sort(Sorted.begin(), Sorted.end());

    map<double, int> myMap;

    for (int i = 0; i < Sorted.size() ; i++)
    {
        myMap.insert(make_pair(Sorted[i],i));
    }

    for (int i = 0; i < myVector.size() ; i++)
    {
        auto it = myMap.find(myVector[i]);
        cout << it->second + 1 << endl;
    }

    return 0;
};

输出:

这是我使用STL以简洁的方式获得排名的代码

template <typename T>
vector<size_t> calRank(const vector<T> & var) {
    vector<size_t> result(var.size());
    //sorted index
    vector<size_t> indx(var.size());
    iota(indx.begin(),indx.end(),0);
    sort(indx.begin(),indx.end(),[&var](int i1, int i2){return var[i1]<var[i2];});
    //return ranking
    for(size_t iter=0;iter<var.size();++iter){
        //it may cause overflow for a really long vector, in practice it should be ok.
        result[indx[iter]]=iter+1;
    }
    return result;
}

这是纯 Armadillo 代码的解决方案,使用函数 arma::sort_index()

函数arma::sort_index()计算排列索引以将给定向量按升序排序。

应用函数arma::sort_index()两次: arma::sort_index(arma::sort_index())},计算 reverse 置换索引,将向量从升序排序回其原始未排序顺序。元素的秩等于 reverse 排列索引。

下面是 Armadillo 封装在 RcppArmadillo 中的代码,它定义了函数 calc_ranks()。函数 calc_ranks() 计算向量元素的秩,可以从 R 调用。

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

// Define the function calc_ranks(), to calculate 
// the ranks of the elements of a vector.
//
// [[Rcpp::export]]
arma::uvec calc_ranks(const arma::vec& da_ta) {
  return (arma::sort_index(arma::sort_index(da_ta)) + 1);
}  // end calc_ranks

以上代码可以保存到文件calc_ranks.cpp,所以可以在R中使用函数编译Rcpp::sourceCpp()

下面是 R 测试函数 calc_ranks() 的代码(在 R 中编译后):

# Compile Rcpp functions
Rcpp::sourceCpp(file="C:/Develop/R/Rcpp/calc_ranks.cpp")

# Create a vector of random data
da_ta <- runif(7)
# Calculate the ranks of the elements
calc_ranks(da_ta)

# Compare with the R function rank()
all.equal(rank(da_ta), drop(calc_ranks(da_ta)))