0

以下のコードを効率的にするための助けを求めています。動作はしますが、満足していません。修正すべきバグがあります (現在は関係ありません)。< random> ヘッダーを初めて使用し、stable_partition を初めて使用しています。

問題の定義/仕様:
数値データ (float 値) の母集団 (ベクトル) があります。ユーザー指定のパーセンテージに基づいて 2 つの RANDOM サンプル (2 つのベクトル) を作成したいと考えています。つまり、popu_data = 30%Sample1 + 70%Sample2 - ここでは 30% がユーザーによって与えられます。% としてはまだ実装していませんが、些細なことです。

プログラミングの問題: 母集団から 30% のサンプルを作成できます。別のベクトルを作成する 2 番目の部分 (sample2 - 70%) は私の問題です。その理由は、30% のデータを選択する際に、値をランダムに選択する必要があるためです。それらを削除するには、インデックスを追跡する必要があります。しかし、私が実装したものよりも効率的なロジックが得られない方法もあります。

私のロジックは (満足ではありません): 人口データでは、ランダムなインデックスの値が一意の値 (ここでは 0.5555) に置き換えられます。後で、Population の個々の値を 0.5555 と比較する stable_partition 関数について知りました。false の場合、そのデータは sample1 を補完する新しい Sample2 として作成されます。

これに加えて、このジェネリックを作成するにはどうすればよいですか。つまり、母集団をユーザー定義の%の母集団のN個のサブサンプルにします。

助けてくれてありがとう。ベクター消去、削除、コピーなどを試みましたが、現在のコードとしては実現しませんでした。より優れた効率的なロジックと stl の使用法を探しています。

#include <random>
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

bool Is05555 (float i){
    if ( i > 0.5560 ) return true;
    return false;
}

int main()
{
    random_device rd;
    mt19937 gen(rd());
    uniform_real_distribution<> dis(1, 2);
    vector<float>randVals;

    cout<<"All the Random Values between 1 and 2"<<endl;
    for (int n = 0; n < 20; ++n) {
        float rnv = dis(gen);
        cout<<rnv<<endl;
        randVals.push_back(rnv);
    }
    cout << '\n';

    random_device rd2;
    mt19937 gen2(rd2());
    uniform_int_distribution<int> dist(0,19);

    vector<float>sample;
    vector<float>sample2;
    for (int n = 0; n < 6; ++n) {
        float rnv = dist(gen2);
        sample.push_back(randVals.at(rnv));
        randVals.at(rnv) = 0.5555;
    }

    cout<<"Random Values between 1 and 2 with 0.5555 a Unique VAlue"<<endl;
    for (int n = 0; n < 20; ++n) {
        cout<<randVals.at(n)<<" ";
    }
    cout << '\n';

    std::vector<float>::iterator bound;
    bound = std::stable_partition (randVals.begin(), randVals.end(), Is05555);

    for (std::vector<float>::iterator it=randVals.begin(); it!=bound; ++it)
        sample2.push_back(*it);

    cout<<sample.size()<<","<<sample2.size()<<endl;

    cout<<"Random Values between 1 and 2 Subset of 6 only: "<<endl;

    for (int n = 0; n < sample.size(); ++n) {
        cout<<sample.at(n)<<" ";
    }
    cout << '\n';

    cout<<"Random Values between 1 and 2 - Remaining: "<<endl;
    for (int n = 0; n < sample2.size(); ++n) {
        cout<<sample2.at(n)<<" ";
    }
    cout << '\n';

    return 0;
}
4

1 に答える 1

1

順序に関係なく、N% サンプルの要件を考えると、次のようなことを行うのがおそらく最も簡単です。

std::random_shuffle(randVals.begin(), randVals.end());
int num = randVals.size() * percent / 100.0;

auto pos = randVals.begin() + randVals.size() - num;

// get our sample
auto sample1{pos, randVals.end()};

// remove sample from original collection
randVals.erase(pos, randVals.end()); 

配列内の項目のタイプによっては、項目を元の配列からサンプル配列に移動することでこれを改善できますが、floatdoubleのような単純なタイプでは何も達成されません。

于 2013-07-20T22:47:45.887 に答える