【问题标题】:(Nearly) Evenly select items from a list(几乎)从列表中均匀选择项目
【发布时间】:2018-03-11 15:59:16
【问题描述】:

我有一个 N 元素列表,我想对间隔尽可能均匀的 M (<= N) 值进行采样。更具体地说,可以说选择应该最小化采样点之间的间距差异。例如,假设我正在构建一个布尔索引数组(即在python 中)来选择元素,

我尝试了算法(来自这个类似但不同的问题:How do you split a list into evenly sized chunks?) :

q, r = divmod(N, M)
indices = [q*jj + min(jj, r) for jj in range(M)]

有时效果很好:

N=11 M=6
good_index = [0 1 0 1 0 1 0 1 0 1 0]

N=14 M=6
good_index = [0 1 1 0 1 1 0 1 0 1 0 1 0 1]

在这里,第一个例子是微不足道的,因为数组可以被平均划分。第二个例子不能等分,但点之间的间距尽量相似(2,2,1,1,1,1)。

但通常效果不佳:

N=16 M=10
bad_index = [0 1 0 1 0 1 0 1 0 1 0 1 0 0 0 0]

N=14 M=10
bad_index = [0 1 0 1 0 1 0 1 0 0 0 0 0 0]

因为你在最后积累了价值。


编辑 1:哎呀,刚刚意识到上面的每个列表在技术上都是颠倒的(0 应该是 1,反之亦然)....但仍然应该传达正确的想法。


编辑 2:上述算法往往效果更好(即通过选择随机数进行目视检查,而不是像概念上更简单的东西,

step = int(floor(N/M))
last = M * step  # this prevents us from getting M+1 elements
indices = [ii for ii in range(0, last, step)]

【问题讨论】:

  • 对于一种快速但看似随机的方法,请查看Halton sequence.
  • @PrestonHager 这很有趣,但您如何看待它在这里有用?

标签: python list math random permutation


【解决方案1】:

查看一些测试的结果(甚至包括上面的测试),问题出在M > N/2 时。 IE。当超过一半的值被采样时。但它适用于M < N/2。所以我目前使用的解决方案只是在M > N/2时反转问题:

注意:这实际上是为 M 元素创建一个大小为 FalseN 屏蔽列表,并尽可能均匀地间隔。

import numpy as np

def even_select(N, M):
    if M > N/2:
        cut = np.zeros(N, dtype=int)
        q, r = divmod(N, N-M)
        indices = [q*i + min(i, r) for i in range(N-M)]
        cut[indices] = True
    else:
        cut = np.ones(N, dtype=int)
        q, r = divmod(N, M)
        indices = [q*i + min(i, r) for i in range(M)]
        cut[indices] = False

    return cut

如果存在更优雅的解决方案,我仍然会感兴趣。

【讨论】:

  • 我打算提出同样的建议。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-02-05
  • 1970-01-01
  • 2016-03-27
  • 2020-09-20
  • 2021-05-14
  • 1970-01-01
  • 2011-11-30
相关资源
最近更新 更多