

Rには、ベクタ`x`のそれぞれに確率を割り振る`sample()`という関数があると思うのですが (`sample(x, size, replace =
FALSE, prob = NULL)`)、同じことをC++ですることは (ライブラリを使うなどすれば)可能でしょうか。  
Eigenライブラリでは、すべての要素に均一の確率しか割り振れないようでしたが、工夫すればできるのでしょうか。


CC BY-SA 3.0
2016-04-27T09:32:01.350
24381
2016-05-04T15:13:45.180
12705
question
c++
C++でのRのsample()


ライブラリは探せばあると思いますが、自分で実装したほうが探すより早いかな。  
sample()の挙動が正しく模擬できているかわかりませんが、以下のように実装してみました。

下記のコードはvisual studio 2015 communityで動作を確認済。

[code]

    #include<random>
    #include<vector>
    #include<numeric>
    #include<iostream>
    
    //Rのsample()の挙動を模擬
    template<class T>
    std::vector<T> sample(const std::vector<T> & vec, const int & num_samples)
    {
        // 乱数の初期値の生成器
        std::random_device rd;
    
        // 乱数生成器
        std::mt19937 generator(rd());
    
        // 一様分布の生成
        std::uniform_int_distribution<int> distribution(0, vec.size()-1);
    
        // 返り値の生成
        std::vector<T> return_val(num_samples);
    
        // あとは結果を添えるだけ
        for (auto & elem : return_val)
        {
            elem = vec[distribution(generator)];
        }
    
        return(return_val);
    }
    
    //Rのsample()の挙動を模擬
    template<class T>
    std::vector<T> sample(const std::vector<T> & vec, const int & num_samples, const std::initializer_list<double> & list)
    {
        if (vec.size() != list.size())
        {
            throw "invalid size\n";
        }
    
        // 乱数の初期値の生成器
        std::random_device rd;
    
        // 乱数生成器
        std::mt19937 generator(rd());
    
        // 一様分布の生成
        std::discrete_distribution<int> distribution(list);
    
        // 返り値の生成
        std::vector<T> return_val(num_samples);
    
        // あとは結果を添えるだけ
        for (auto & elem : return_val)
        {
            elem = vec[distribution(generator)];
        }
    
        return(return_val);
    }
    
    int main()
    {
        // 動くか確認
        std::vector<int> num(5);
    
        std::iota(num.begin(), num.end(), 0);
    
        std::cout << "確率に比重がある場合:\n";
    
        {
            auto vec = sample(num, 10, { 0.5,2.1,3,0.4,10.0 });
    
            // 出力
            for (auto & elem : vec)
            {
                std::cout << elem << ", ";
            }
    
            std::cout << std::endl;
        }
    
        std::cout << "一様な確率の場合:\n";
    
        {
            auto vec = sample(num, 10);
    
            // 出力
            for (auto & elem : vec)
            {
                std::cout << elem << ", ";
            }
    
            std::cout << std::endl;
        }
    
        return 0;
    }
    
[/code]


CC BY-SA 3.0
2016-05-04T15:01:22.897
24568
2016-05-04T15:13:45.180
2016-05-04T15:13:45.180
24381
answer