如何从向量中取n个样本?

3
我的问题是如何从vec.begin()vec.end()中选择n个元素,以便我们几乎覆盖了所有的向量元素?
vector<double> take_100_samples(vector<double>& in)
{
  vector<double> vec(100);
  double step = (in.size() - 1) / (100 - 1);

// sampling process

  return vec;
} 

例如,如果向量 in 的大小为 200,则我们选择其中每两个元素(即in[0]in[2]in[4],...,in[199]),但如果大小不能被 100 整除怎么办?
是否有有效的方法来解决这个问题?
敬礼

15
你可能需要的是 std::sample 函数。 - Albin Paul
1
当你只取样本时,“覆盖所有元素”是什么意思?这是关于向量中存储的值的范围吗?这是关于确保至少取第一个和最后一个吗?如果向量中的元素少于100个怎么办? - Christophe
@Christophe,对于大小为200且步长为2的向量,我们几乎覆盖了所有元素...这只是一个好的步长定义。而且我们总是确保输入向量的大小大于100。 - student_11
1
我认为在这里使用带有random_device的std::sample不够充分,因为它不能保证结果的均匀性。也就是说,在200个元素中,不能保证每隔一个元素就会被选中! - user1810087
确切地说,这个问题中没有随机性,它是均匀采样的,而不是随机均匀采样。 - Matthieu Brucher
2个回答

2
通常的做法是将浮点数转换为分数,然后四舍五入为整数:
double step = in.size() / 100.;

for(int i = 0; i < 100; ++i)
{
    auto index = std::lround(i * step);
    // use index
}

当然,如果你想始终获取第一个和最后一个元素,就像之前一样调整步数计算以及循环。

4
需要除以100.0,否则会出现整数除法的情况。 - Aconcagua
当然可以...我修改了我的帖子,不小心删除了双重转换... - Matthieu Brucher
1
关于术语的一点说明:你所舍入的整数并不是分数步长,而是相位 = i * 步长。无论如何,这是一个好的快速解决方案。 - Damien
1
一种简单的强制选择第一个和最后一个元素的方法是使用 step = (in.size() -1)/99.0; - Damien
是的,那就是 OP 使用的方法,也是我说他可以根据要选择的元素来使用的方法。 - Matthieu Brucher

1
我的理解是你想对一个异步频率的信号进行降采样。
一种方法是实现一种数字锁相环(Digital PLL)。
假设输入有N = 1030个元素,你想要得到K = 100个元素。平均速率等于rate = 10.3。在实践中,你将不得不使用一个步长等于10或11,具体取决于当前索引的位置。
如果你处于“滞后”状态:步长=11(加速) 如果你处于“超前”状态:步长=10(减速)
测试是否滞后或超前: 当前“读取”索引i等于以前步骤的总和。k是输出索引。 如果i < rate*k,则你落后了;否则你超前了。
这是基本思路。还可以进行一些小的调整,例如确保获取最后一个元素。

编辑:我刚刚“重新发现”了Mathieu Brucher的解决方案。在第一次阅读时,我被他的答案中步骤计算的原始错误(已更正)误导了。很明显,结果将是等效的,除了Mathieu Brucher的实现更简单。在这种情况下,我的回答唯一的意义是提供另一种过程的解释。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接