从长度为n的序列中选择m个均匀间隔的元素

时间:2012-03-26 14:05:28

标签: python algorithm

我有一个n个元素的向量/数组。我想选择m个元素。

选择必须公平/确定 - 每个小节同样多。

当m = 10,n = 20时很容易:只需要每隔一个元素。 但是在一般情况下如何做呢?我是否需要计算液晶显示屏?

5 个答案:

答案 0 :(得分:28)

您可能需要Bresenham's line algorithm。从m统一选择n元素相当于在m x n离散像素网格中绘制一条线。在x .. 0n-1坐标y .. 0中假设m-1坐标,并且如果您在(0,0)和(n-1,m-1)。每当y坐标发生变化时,请从索引x中选择一个元素。

UPD:但似乎这个简单的功能就足够你了:

>>> f = lambda m, n: [i*n//m + n//(2*m) for i in range(m)]
>>> f(1,20)
[10]
>>> f(2,20)
[5, 15]
>>> f(3,20)
[3, 9, 16]
>>> f(5,20)
[2, 6, 10, 14, 18]

答案 1 :(得分:13)

这是一个简单的例子:

from math import ceil

def takespread(sequence, num):
    length = float(len(sequence))
    for i in range(num):
        yield sequence[int(ceil(i * length / num))]
使用

math.ceil是因为没有它,所选择的索引将在每个隐式子部分的开头加权太多,结果就是整个列表。

答案 2 :(得分:3)

这将始终选择第一个和最后一个元素:

which_idxs = lambda m, n: np.rint( np.linspace( 1, n, min(m,n) ) - 1 ).astype(int)

evenly_spaced = np.array( your_list )[which_idxs(m,n)]

如果m大于n,则仅选择最多n个元素。

如果你真的希望它在整个阵列中均匀分布,即使在最后也是如此,那么它就是这样:

which_idxs = lambda m, n: [idx for idx in np.rint( np.linspace( 1-n/(2*min(m,n)), n+n/(2*min(m,n)), min(m,n)+2 ) - 1 ).astype(int) if idx in range(n)]

evenly_spaced = np.array( your_list )[which_idxs(m,n)]

这给你这样的东西:

>>> np.array( [1, 2, 3, 'a', 'b', 'c'] )[which_idxs(m,n)]
Out: array(['2', 'b'])

答案 3 :(得分:2)

使用循环(int i = 0; i< m; i ++)

然后获得你想要的索引,Ceil(i * m / n)。

答案 4 :(得分:0)

我正在进行临床应用,发现上面的所有答案都有不同程度的偏见。这是另一种解决方案,即使在一个圆圈中也能很好地工作。也就是说,即使最后一个数字包围在你使用度0°= 360°时也是如此。

import numpy as np
m = 51
# Generate intervals
epts = np.linspace(0,360,m+1,endpoint=True)
# Create the halfsteps between intervals (One would have sufficed)
halfsteps = (epts[1:] - epts[:-1]) / 2
# Find the midpoints
midpoints = epts[:-1] + halfsteps
# Make an unbiased rounding
results = np.around(midpoints, decimals=0)