簡體   English   中英

用numpy重復一個范圍

[英]repeat arange with numpy

我有一個帶整數值的數組。

a = [2,1,4,0,2]

我希望對a中的每個值應用arange函數,以便:

b = [0,1,0,0,1,2,3,1,2]
b "=" [arange(2),arange(1),arange(4),arange(0),arange(2)] 

實際上我使用np.repeat函數根據數組a重復數組行,並且我希望有一個標記i來將每個重復值鏈接到原始值並且有一個標識號然后區分它們。

我嘗試使用np.vectorize,但沒有成功。

肯定有更多的numpythonic做事方式。 一種可能性可能是這樣的:

import numpy as np
from numpy.lib.stride_tricks import as_strided

def concatenated_ranges(ranges_list) :
    ranges_list = np.array(ranges_list, copy=False)
    base_range = np.arange(ranges_list.max())
    base_range =  as_strided(base_range,
                             shape=ranges_list.shape + base_range.shape,
                             strides=(0,) + base_range.strides)
    return base_range[base_range < ranges_list[:, None]]

如果你只連接幾個范圍,那么E先生的純蟒蛇解決方案可能是你最好的選擇,但是如果連接的范圍都要少到一百個,那么這個星星的速度會明顯加快。 為了比較,我使用了從其他答案中提取的這兩個函數:

def junuxx(a) :
    b = np.array([], dtype=np.uint8)
    for x in a:
        b = np.append(b, np.arange(x))
    return b

def mr_e(a) :
    return reduce(lambda x, y: x + range(y), a, [])

以下是一些時間安排:

In [2]: a = [2, 1, 4, 0 ,2] # the OP's original example

In [3]: concatenated_ranges(a) # show it works!
Out[3]: array([0, 1, 0, 0, 1, 2, 3, 0, 1])

In [4]: %timeit concatenated_ranges(a)
10000 loops, best of 3: 31.6 us per loop

In [5]: %timeit junuxx(a)
10000 loops, best of 3: 34 us per loop

In [6]: %timeit mr_e(a)
100000 loops, best of 3: 2.58 us per loop

In [7]: a = np.random.randint(1, 10, size=(10,))

In [8]: %timeit concatenated_ranges(a)
10000 loops, best of 3: 27.1 us per loop

In [9]: %timeit junuxx(a)
10000 loops, best of 3: 79.8 us per loop

In [10]: %timeit mr_e(a)
100000 loops, best of 3: 7.82 us per loop

In [11]: a = np.random.randint(1, 10, size=(100,))

In [12]: %timeit concatenated_ranges(a)
10000 loops, best of 3: 57.4 us per loop

In [13]: %timeit junuxx(a)
1000 loops, best of 3: 756 us per loop

In [14]: %timeit mr_e(a)
10000 loops, best of 3: 149 us per loop

In [15]: a = np.random.randint(1, 10, size=(1000,))

In [16]: %timeit concatenated_ranges(a)
1000 loops, best of 3: 358 us per loop

In [17]: %timeit junuxx(a)
100 loops, best of 3: 9.38 ms per loop

In [18]: %timeit mr_e(a)
100 loops, best of 3: 8.93 ms per loop

我的答案類似於Junuxx - 我不確定你給出的答案是你想要的答案

a = [2, 1, 4, 0 ,2]
reduce(lambda x, y: x+range(y), a, [])

給我

[0, 1, 0, 0, 1, 2, 3, 0, 1]

這確實你仿佛被描述,即aranges的級聯在所有的值a 雖然這意味着你給出的b有一些錯誤:

>>> a = [2, 1, 4, 0, 2]
>>> b = np.array([], dtype=np.uint8)
>>>for x in a:
>>>    b = np.append(b, np.arange(x))
>>> print b
array([0,1,0,0,1,2,3,0,1,])

在你的編輯解釋你想要一個列表的列表之后,我認為這會更有效:

>>> a = [2, 1, 4, 0, 2]
>>> b = [np.arange(x) for x in a]
>>> print b
[array([0, 1]), array([0]), array([0, 1, 2, 3]), array([], dtype=int32),
 array([0, 1])]

另一種通常更節省內存的方法,並且速度稍快:

import numpy as np
def concatenated_ranges2(ranges_list):
    cumsum = np.append(0, np.cumsum(ranges_list[:-1]))
    cumsum = np.repeat(cumsum, ranges_list)
    return np.arange(cumsum.shape[0]) - cumsum

測試此功能和前一個功能:

>>> a = np.random.randint(1, 10, size=(1000,))
>>> %timeit concatenated_ranges(a)
10000 loops, best of 3: 142 us per loop
>>> %timeit concatenated_ranges2(a)
10000 loops, best of 3: 72.6 us per loop

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM