【问题标题】:How to create equal spaced values in between unequal spaced values in Python?如何在 Python 中的不等间距值之间创建等间距值?
【发布时间】:2015-06-09 06:43:24
【问题描述】:

我有一个数组 A(变量),形式为:

A = [1, 3, 7, 9, 15, 20, 24]

现在我想在数组 A 的值之间创建 10 个(变量)等间距的值,以便我得到以下形式的数组 B:

B = [1, 1.2, 1.4, ... 2.8, 3, 3.4, 3.8, ... , 6.6, 7, 7.2, ..., 23.6, 24]

本质上,B 应该始终具有 A 的值以及 A 的值之间等距的值。

我确实通过使用代码解决了这个问题:

import numpy as np
A = np.array([1, 3, 7, 9, 15, 20, 24])
B = []
for i in range(len(A) - 1):
    B = np.append(B, np.linspace(A[i], A[i + 1], 11))
print (B)

但是 NumPy 是否已经有任何函数或者是否有其他更好的方法来创建这样的数组。

【问题讨论】:

    标签: python arrays numpy scipy


    【解决方案1】:

    你可以在列表理解和np.concatenate 中使用zip 函数,但是如果你也想要最后一个元素,你可以在它后面加上np.append

    >>> np.append(np.concatenate([np.linspace(i, j, 10, False) for i,j in zip(A,A[1:])]),A[-1])
    array([  1. ,   1.2,   1.4,   1.6,   1.8,   2. ,   2.2,   2.4,   2.6,
             2.8,   3. ,   3.4,   3.8,   4.2,   4.6,   5. ,   5.4,   5.8,
             6.2,   6.6,   7. ,   7.2,   7.4,   7.6,   7.8,   8. ,   8.2,
             8.4,   8.6,   8.8,   9. ,   9.6,  10.2,  10.8,  11.4,  12. ,
            12.6,  13.2,  13.8,  14.4,  15. ,  15.5,  16. ,  16.5,  17. ,
            17.5,  18. ,  18.5,  19. ,  19.5,  20. ,  20.4,  20.8,  21.2,
            21.6,  22. ,  22.4,  22.8,  23.2,  23.6,  24. ])
    

    您也可以使用retstep=True 来返回(samples, step),其中step 是样本之间的间距。

    >>> np.concatenate([np.linspace(i, j, 10, False,retstep=True) for i,j in zip(A,A[1:])])
    array([array([ 1. ,  1.2,  1.4,  1.6,  1.8,  2. ,  2.2,  2.4,  2.6,  2.8]),
           0.2,
           array([ 3. ,  3.4,  3.8,  4.2,  4.6,  5. ,  5.4,  5.8,  6.2,  6.6]),
           0.4,
           array([ 7. ,  7.2,  7.4,  7.6,  7.8,  8. ,  8.2,  8.4,  8.6,  8.8]),
           0.2,
           array([  9. ,   9.6,  10.2,  10.8,  11.4,  12. ,  12.6,  13.2,  13.8,  14.4]),
           0.6,
           array([ 15. ,  15.5,  16. ,  16.5,  17. ,  17.5,  18. ,  18.5,  19. ,  19.5]),
           0.5,
           array([ 20. ,  20.4,  20.8,  21.2,  21.6,  22. ,  22.4,  22.8,  23.2,  23.6]),
           0.4], dtype=object)
    

    【讨论】:

    • 我认为 OP 希望两个数字之间有 10 个等距变量。
    【解决方案2】:

    基本上是您原始方法的略微浓缩版本:

    print np.hstack(np.linspace(a, b, 10, endpoint=False) for a, b in zip(A[:-1], A[1:]))
    

    输出:

    [  1.    1.2   1.4   1.6   1.8   2.    2.2   2.4   2.6   2.8   3.    3.4
       3.8   4.2   4.6   5.    5.4   5.8   6.2   6.6   7.    7.2   7.4   7.6
       7.8   8.    8.2   8.4   8.6   8.8   9.    9.6  10.2  10.8  11.4  12.
      12.6  13.2  13.8  14.4  15.   15.5  16.   16.5  17.   17.5  18.   18.5
      19.   19.5  20.   20.4  20.8  21.2  21.6  22.   22.4  22.8  23.2  23.6]
    

    endpoint 参数控制在两个原始值之间是否有 9 个或 10 个等距值


    编辑

    由于您希望最后是 24,您可以像 Kasra 那样使用 append 或者 -- 提出一些变化;) -- 忘记 endpoint 参数并从 @987654327 生成 10 + 1 值@到b。这将自动附加 24(因为 endpoint 默认为真)。 (更新:正如 Bas Swinckels 所说,您现在需要用 unique 包装它......)

    print np.unique(np.hstack(np.linspace(a, b, 10 + 1) for a, b in zip(A[:-1], A[1:])))
    
    [  1.    1.2   1.4   1.6   1.8   2.    2.2   2.4   2.6   2.8   3.
       3.4   3.8   4.2   4.6   5.    5.4   5.8   6.2   6.6   7.    7.2
       7.4   7.6   7.8   8.    8.2   8.4   8.6   8.8   9     9.6  10.2
      10.8  11.4  12.   12.6  13.2  13.8  14.4  15.   15.5  16.   16.5
      17.   17.5  18.   18.5  19.   19.5  20.   20.4  20.8  21.2  21.6
      22.   22.4  22.8  23.2  23.6  24. ]
    

    【讨论】:

    • OP 想要24 在尾随!
    • @Kasra:感谢您的提示!我相应地更新了我的答案。
    • 这也不行,你现在有像 3 double 这样的内部点!
    【解决方案3】:

    使用interpolation 代替串联的替代方法:

    n = 10
    x = np.arange(0, n * len(A), n)       # 0, 10, .., 50, 60
    xx = np.arange((len(A) - 1) * n + 1)  # 0, 1, .., 59, 60
    B = np.interp(xx, x, A)
    

    结果:

    In [31]: B
    Out[31]: 
    array([  1. ,   1.2,   1.4,   1.6,   1.8,   2. ,   2.2,   2.4,   2.6,
             2.8,   3. ,   3.4,   3.8,   4.2,   4.6,   5. ,   5.4,   5.8,
             6.2,   6.6,   7. ,   7.2,   7.4,   7.6,   7.8,   8. ,   8.2,
             8.4,   8.6,   8.8,   9. ,   9.6,  10.2,  10.8,  11.4,  12. ,
            12.6,  13.2,  13.8,  14.4,  15. ,  15.5,  16. ,  16.5,  17. ,
            17.5,  18. ,  18.5,  19. ,  19.5,  20. ,  20.4,  20.8,  21.2,
            21.6,  22. ,  22.4,  22.8,  23.2,  23.6,  24. ])
    

    这应该比其他解决方案更快,因为它不使用 Python for 循环,也不会对 linspace 进行多次调用。快速时序比较:

    In [58]: timeit np.interp(np.arange((len(A) - 1) * 10 + 1), np.arange(0, 10*len(A), 10), A)
    100000 loops, best of 3: 10.3 µs per loop
    
    In [59]: timeit np.append(np.concatenate([np.linspace(i, j, 10, False) for i, j in zip(A, A[1:])]), A[-1])
    10000 loops, best of 3: 94.2 µs per loop
    
    In [60]: timeit np.unique(np.hstack(np.linspace(a, b, 10 + 1) for a, b in zip(A[:-1], A[1:])))
    10000 loops, best of 3: 140 µs per loop
    

    【讨论】:

      【解决方案4】:

      解决方案代码

      此解决方案建议使用broadcastingmatrix multiplication 的矢量化方法。

      基本步骤是:

      1. 将不包括1[0,1) 的单位步长间隔划分为具有相等步长且长度为steps 的元素数组。

      2. 然后,将这些步进数组元素中的每一个元素与A 的微分相乘,以获得偏移插值元素的二维数组。

      3. 最后,为实际插值添加A 元素。

      这是实现 -

      out2D = (np.diff(A)[:,None]*np.arange(steps)/steps) + A[:-1,None]
      out = np.append(out2D,A[-1])
      

      基准测试

      建议的方法似乎比 other solution 中针对中型到大型输入数组所建议的基于实际插值的方法更快,因为我们正在使用常规模式来插值值。这里有一些运行时测试来确认 -

      案例 #1:A 的长度为 100steps = 10

      In [42]: A = np.sort(np.random.randint(1,100000,(1,100))).ravel()
      
      In [43]: steps = 10
      
      In [44]: %timeit interp_based(A,steps)
      100000 loops, best of 3: 18.3 µs per loop
      
      In [45]: %timeit broadcasting_based(A,steps)
      100000 loops, best of 3: 19.7 µs per loop
      

      案例 #2:A 的长度为 500steps = 10

      In [46]: A = np.sort(np.random.randint(1,100000,(1,500))).ravel()
      
      In [47]: steps = 10
      
      In [48]: %timeit interp_based(A,steps)
      10000 loops, best of 3: 101 µs per loop
      
      In [49]: %timeit broadcasting_based(A,steps)
      10000 loops, best of 3: 48.8 µs per loop
      

      案例 #3:A 的长度为 1000steps = 20

      In [50]: A = np.sort(np.random.randint(1,100000,(1,1000))).ravel()
      
      In [51]: steps = 20
      
      In [52]: %timeit interp_based(A,steps)
      1000 loops, best of 3: 345 µs per loop
      
      In [53]: %timeit broadcasting_based(A,steps)
      10000 loops, best of 3: 139 µs per loop
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-04-02
        • 1970-01-01
        • 1970-01-01
        • 2020-07-11
        • 2018-01-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多