对数间隔的整数

and*_*ndy 18 python numpy resampling

假设我有一个10,000磅的矢量,我想采取一个只有100个对数间隔点的切片.我想要一个函数给我索引的整数值.这是一个简单的解决方案,只需使用+ 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)
Run Code Online (Sandbox Code Playgroud)

请注意,有16个重复,所以现在我只有84个点.

有没有人有一个能够有效确保输出样本数量为num的解决方案?对于此特定示例,num为121和122的输入值给出100个输出点.

Ava*_*ris 17

这有点棘手.您不能总是得到对数间隔的数字.在您的示例中,第一部分是相当线性的.如果你对此感到满意,我有一个解决方案.但是对于解决方案,您应该理解为什么有重复项.

对数标度满足条件:

s[n+1]/s[n] = constant
Run Code Online (Sandbox Code Playgroud)

让我们把这种恒定rratio.对于n范围之间的这些数字1...size,您将得到:

1, r, r**2, r**3, ..., r**(n-1)=size
Run Code Online (Sandbox Code Playgroud)

所以这给你:

r = size ** (1/(n-1))
Run Code Online (Sandbox Code Playgroud)

在你的情况下,n=100并且size=10000,r将来~1.0974987654930561,这意味着,如果你开始1,你的下一个数字将再次1.0974987654930561四舍五入1.因此你的重复.此问题适用于小数字.在足够大的数字之后,乘以比率将导致不同的舍入整数.

记住这一点,最好的办法是将连续的整数添加到某个点,这样这个乘以比率就不再是问题了.然后,您可以继续使用对数缩放.以下功能可以:

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)
Run Code Online (Sandbox Code Playgroud)

Python 3更新:最后一行曾经 return np.array(map(lambda x: round(x)-1, result), dtype=np.uint64) 在Python 2中

以下是使用它的一些示例:

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)
Run Code Online (Sandbox Code Playgroud)

只是为了向您展示结果的对数性,这里是输出的半对数图x = gen_log_scale(10000, 100)(如您所见,左侧部分不是真正的对数):

在此输入图像描述