【问题标题】:Sampling Data into two Groups将数据抽样到两组
【发布时间】:2013-07-19 22:39:28
【问题描述】:

我正在寻求帮助以使下面的代码高效。尽管它有效,但我并不满意。有需要修复的错误(当前无关)。我第一次使用 标头,第一次使用 stable_partition。

问题定义/规范:
我有一个数值数据(浮点值)的总体(向量)。我想根据用户指定的百分比创建两个 RANDOM 样本(2 个向量)。即 popu_data = 30%Sample1 + 70%Sample2 - 这里 30% 将由用户给出。我还没有实现为 % 但它微不足道。

编程中的问题:我能够从总体中创建 30% 的样本。创建另一个向量(sample2 - 70%)的第二部分是我的问题。原因是在选择 30% 的数据时,我必须随机选择值。我必须跟踪索引以删除它们。但是有些我没有得到比我实现的逻辑更有效的逻辑。

我的逻辑是(不高兴):在人口数据中,随机索引处的值被替换为唯一值(这里是 0.5555)。后来我了解了 stable_partition 函数,其中将 Population 的各个值与 0.5555 进行比较。设置为 false 时,该数据将创建为与 sample1 互补的新 Sample2。

除此之外:我怎样才能使这个 Generic 即人口成为用户定义的人口百分比的 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;
}

【问题讨论】:

  • 算法函数 set_difference 可能会救我 - 刚刚看到该函数在右侧栏弹出。但是,似乎我必须在使用之前进行排序,这并不令人信服。
  • 对于您的 30% 样本,您是否需要以 30% 的概率选择每个样本(可能导致样本量略微与 30% 不同)或恰好 30% 的项目选择?您需要原始顺序的结果,还是样品的顺序无关紧要?
  • vector&lt;float&gt;sample; for (int n = 0; n &lt; 6; ++n) { float rnv = dist(gen2); sample.push_back(randVals.at(rnv)); } sort(randVals.begin(), randVals.end()); sort(sample.begin(), sample.end()); vector &lt;float&gt; sample2; set_difference(randVals.begin(), randVals.end(), sample.begin(), sample.end(),inserter(sample2,sample2.end())); 使用 set_difference 的代码 - 它有效
  • @JerryCoffin - 对于我目前的需求,概率无关紧要。目前避免了这种复杂性。 30% 仅表示来自总体的 30% 的数据/值。我考虑了顺序 - 样本的顺序无关紧要。我面临另一个问题:在我的代码中,行(n

标签: c++ random stl stl-algorithm subsampling


【解决方案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 这样的简单类型,这将无济于事。

【讨论】:

  • 谢谢。寻找清晰高效的代码。我们要么随机选择(我实现的那个——又长又脏),要么随机随机播放,然后从馅饼中得到一个连续的部分(清晰而高效)——谢谢。
  • 根据这篇帖子:stackoverflow.com/questions/13459953/…,我想我应该在你提到的 5 行之上使用 srand 函数????谢谢你。 !! std::srand(std::time(0));
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-05-31
  • 2013-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-28
相关资源
最近更新 更多