我有一个n个元素的向量/数组。我想选择m个元素。
选择必须公平/确定 - 每个小节同样多。
当m = 10,n = 20时很容易:只需要每隔一个元素。 但是在一般情况下如何做呢?我是否需要计算液晶显示屏?
答案 0 :(得分:28)
您可能需要Bresenham's line algorithm。从m
统一选择n
元素相当于在m
x n
离散像素网格中绘制一条线。在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]
答案 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)