假设我有一个10000点的向量,我想取一个只有100个对数间隔点的切片。我想要一个函数给我一个索引的整数值。这是一个简单的解决方案,只需使用around+logspace,然后去掉重复项。

def genLogSpace( array_size, num ):
    lspace = around(logspace(0,log10(array_size),num)).astype(uint64)
    return array(sorted(set(lspace.tolist())))-1

ls=genLogspace(1e4,100)

print ls.size
>>84
print ls
array([   0,    1,    2,    3,    4,    5,    6,    7,    8,    9,   10,
         11,   13,   14,   15,   17,   19,   21,   23,   25,   27,   30,
         33,   37,   40,   44,   49,   54,   59,   65,   71,   78,   86,
         94,  104,  114,  125,  137,  151,  166,  182,  200,  220,  241,
        265,  291,  319,  350,  384,  422,  463,  508,  558,  613,  672,
        738,  810,  889,  976, 1071, 1176, 1291, 1416, 1555, 1706, 1873,
       2056, 2256, 2476, 2718, 2983, 3274, 3593, 3943, 4328, 4750, 5213,
       5721, 6279, 6892, 7564, 8301, 9111, 9999], dtype=uint64)

注意有16个副本,所以现在我只有84分。
是否有人有一个能够有效地确保输出样本数为num的解决方案?对于这个特定的例子,num为121和122的输入值给出100个输出点。

最佳答案

这有点棘手。你不能总是得到对数间隔的数字。在您的示例中,第一部分是相当线性的。如果你同意的话,我有一个解决办法。但是对于解决方案,您应该理解为什么您有重复项。
对数刻度满足条件:

s[n+1]/s[n] = constant

让我们把这个常数称为rforratio。对于n范围之间的这些数字,您将得到:
1, r, r**2, r**3, ..., r**(n-1)=size

所以这给了你:
r = size ** (1/(n-1))

在您的情况下,1...sizen=100size=10000将是r,这意味着,如果您从~1.0974987654930561开始,您的下一个数字将是1然后再次四舍五入到1.0974987654930561。所以你的复制品。这个问题只针对少数人。在一个足够大的数字之后,乘以比率将得到一个不同的整数。
记住这一点,您的最佳选择是将连续整数相加到某个点,这样与比率相乘就不再是问题了。然后可以继续使用对数比例。以下函数执行此操作:
import numpy as np

def gen_log_space(limit, n):
    result = [1]
    if n>1:  # just a check to avoid ZeroDivisionError
        ratio = (float(limit)/result[-1]) ** (1.0/(n-len(result)))
    while len(result)<n:
        next_value = result[-1]*ratio
        if next_value - result[-1] >= 1:
            # safe zone. next_value will be a different integer
            result.append(next_value)
        else:
            # problem! same integer. we need to find next_value by artificially incrementing previous value
            result.append(result[-1]+1)
            # recalculate the ratio so that the remaining values will scale correctly
            ratio = (float(limit)/result[-1]) ** (1.0/(n-len(result)))
    # round, re-adjust to 0 indexing (i.e. minus 1) and return np.uint64 array
    return np.array(list(map(lambda x: round(x)-1, result)), dtype=np.uint64)

python 3更新:python 2中的最后一行过去是1
下面是一些使用它的示例:
In [157]: x = gen_log_space(10000, 100)

In [158]: x.size
Out[158]: 100

In [159]: len(set(x))
Out[159]: 100

In [160]: y = gen_log_space(2000, 50)

In [161]: y.size
Out[161]: 50

In [162]: len(set(y))
Out[162]: 50

In [163]: y
Out[163]:
array([   0,    1,    2,    3,    4,    5,    6,    7,    8,    9,   11,
         13,   14,   17,   19,   22,   25,   29,   33,   38,   43,   49,
         56,   65,   74,   84,   96,  110,  125,  143,  164,  187,  213,
        243,  277,  316,  361,  412,  470,  536,  612,  698,  796,  908,
       1035, 1181, 1347, 1537, 1753, 1999], dtype=uint64)

为了向您展示结果的对数性,这里是输出return np.array(map(lambda x: round(x)-1, result), dtype=np.uint64)的半对数图(如您所见,左侧部分不是真正的对数):

关于python - 对数间隔的整数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12418234/

10-12 20:57