Python 从长度为n的序列中选择m个等距元素

Python 从长度为n的序列中选择m个等距元素,python,algorithm,Python,Algorithm,我有一个n个元素的向量/数组。我想选择m个元素 选择必须是公平的/确定性的-每个小节中的选择数量相等 当m=10,n=20时,很容易:只需每秒钟取一个元素。 但在一般情况下怎么做呢?我必须计算LCD吗?您可能需要。从n中均匀选择m个元素相当于在mxn离散像素网格中画一条线。假设x坐标为0..n-1,y坐标为0..m-1,继续进行,就像在0,0和n-1,m-1之间画一条线一样。每当y坐标发生变化时,从索引x中拾取一个元素 UPD:但似乎这个简单的函数就足够了: >>> f = l

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

选择必须是公平的/确定性的-每个小节中的选择数量相等

当m=10,n=20时,很容易:只需每秒钟取一个元素。 但在一般情况下怎么做呢?我必须计算LCD吗?

您可能需要。从n中均匀选择m个元素相当于在mxn离散像素网格中画一条线。假设x坐标为0..n-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]

使用循环int i=0;i
然后,为了获得所需的索引,Ceili*m/n.

这里有一个快速示例:

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,是因为如果没有它,所选的索引将在每个隐式小节的开头加权过多,从而导致整个列表。

我正在研究一个临床应用程序,发现上面的所有答案都有不同程度的偏差。这里有另一个解决方案,即使在一个循环中也能很好地工作。也就是说,即使使用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)

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

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'])

选择第一个m元素有什么错?你似乎暗示存在某种约束,但你没有描述它。你的意思是让m的位置均匀分布在n上吗?@AmrinderArora也许我很厚,但如果n不是m的倍数怎么办?例如,n=1234,m=1000。我需要在每个小节中有相同数量的这是怎么回事?我看不出你的问题有任何推论。你想要原始数组的等距子样本。你为什么不这么说?我们为什么需要ceil?int截断不会起作用吗,即只产生序列[i*length/num]@j13r如果使用隐式floor,对象将向列表的开头加权过多。那么舍入是否更有意义?@j13r这样想。第一个索引始终为零。这些索引是近似等距的。如果不使用ceil,您将永远无法获得最后一项。因此,在第一项和最后一项之前的某项之间有一个均匀的采样。因此,示例中的中间索引小于序列的中间索引。因为//也适用于Python 2,所以在表示截断除法时最好显式使用它。您可以使用middpoints=epts[1:]+epts[:-1]/2计算中点,当M太大时,半步可能太小,应该有相同或更好的结果。