在numpy中复制matlab dyadup

2024-10-04 03:28:26 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图在numpy中复制Matlab中的dyadup函数。有比这更有效的方法吗np.插入()? 你知道吗

import numpy as np

def dyadup(a, level=1, even=False):
    if even == False:
        start = 1
        end = len(a) + 1
    else:
        start = 0
        end = len(a)
    x = a
    for l in range(level):
      x = np.insert(x, range(start, end), 0)
    return x

用一个1024元素的初始数组快速计时,我得到了每个循环14.2usec的最佳时间,这还不错,但我想知道是否可以做得更好。你知道吗

谢谢!你知道吗


Tags: 方法函数importnumpyfalselenasnp
1条回答
网友
1楼 · 发布于 2024-10-04 03:28:26

更有效的方法是:

import numpy as np

def dyadup(a, level=1, even=False):
    level += 1
    start = 1 if even else 0
    out = np.zeros(len(a) * level, dtype=a.dtype)
    out[start::level] = a
    return out

更多细节

让我把这个分解一下。你知道吗

在python(类似于Matlab)中,我们可以通过切片操作引用或提取有规则间隔的项目。例如:

In [1]: import numpy as np

In [2]: x = np.arange(10)

In [3]: x
Out[3]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

In [4]: x[::2]
Out[4]: array([0, 2, 4, 6, 8])

In [5]: x[1::2]
Out[5]: array([1, 3, 5, 7, 9])

In [6]: x[1::3]
Out[6]: array([1, 4, 7])

我们还可以使用它将项分配给数组:

In [7]: y = np.zeros(10)

In [8]: y
Out[8]: array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.])

In [9]: y[1::3] = 9

In [10]: y
Out[10]: array([ 0.,  9.,  0.,  0.,  9.,  0.,  0.,  9.,  0.,  0.])

In [11]: y[1::3] = 4, 5, 6

In [12]: y
Out[12]: array([ 0.,  4.,  0.,  0.,  5.,  0.,  0.,  6.,  0.,  0.])

因此,我们可以这样做:

In [13]: data = np.random.random(5)

In [14]: data
Out[14]: array([ 0.05458934,  0.97719278,  0.49670205,  0.87299456,  0.2223557 ])

In [15]: interleaved = np.zeros(len(data) * 2)

In [16]: interleaved[::2] = data

In [17]: interleaved
Out[17]: 
array([ 0.05458934,  0.        ,  0.97719278,  0.        ,  0.49670205,
        0.        ,  0.87299456,  0.        ,  0.2223557 ,  0.        ])

对于大型数组,这比使用insert要有效得多,因为每次调用insert时都会生成数组的副本。你知道吗


时机

以时差为例

In [2]: data = np.arange(10000)

In [3]: %timeit dyadup(data)
10000 loops, best of 3: 33 µs per loop

In [4]: %timeit orig_dyadup(data)
100 loops, best of 3: 2.21 ms per loop

请注意micro和milli。新的实现速度快了约100倍。你知道吗


进一步考虑

另外,注意不要修改您的输入。在python中x = a不复制ax是同一个对象,因此对x的任何修改也是对a的修改。你知道吗

在这个特定的例子中,np.insert生成一个副本,这样您就不会修改您的输入,但在其他情况下您会这样做。你知道吗


最后一点,如果我正确理解了原始函数的意图,那么level大于1就是不正确的。你知道吗

例如:

In [5]: orig_dyadup(range(10), 3)
Out[5]: 
array([0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3,
       0, 0, 0, 4, 0, 0, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0])

In [6]: dyadup(range(10), 3)
Out[6]: 
array([0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0,
       0, 6, 0, 0, 0, 7, 0, 0, 0, 8, 0, 0, 0, 9, 0, 0, 0])

之所以会出现这种差异,是因为您在迭代时修改了某些内容,但在插入时引用了原始项的索引。不过,我可能误解了你的意图。你知道吗

相关问题 更多 >