簡體   English   中英

生成級聯范圍的一維NumPy數組

[英]Generate 1D NumPy array of concatenated ranges

我想生成以下數組a

nv = np.random.randint(3, 10+1, size=(1000000,))
a = np.concatenate([np.arange(1,i+1) for i in nv])

因此,輸出將類似於-

[0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 0, 1, 2, 3, 4, 5, 0, ...]

有沒有更好的方法呢?

這是使用cumulative summation的矢量化方法-

def ranges(nv, start = 1):
    shifts = nv.cumsum()
    id_arr = np.ones(shifts[-1], dtype=int)
    id_arr[shifts[:-1]] = -nv[:-1]+1
    id_arr[0] = start # Skip if we know the start of ranges is 1 already
    return id_arr.cumsum()

樣品運行-

In [23]: nv
Out[23]: array([3, 2, 5, 7])

In [24]: ranges(nv, start=0)
Out[24]: array([0, 1, 2, 0, 1, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6])

In [25]: ranges(nv, start=1)
Out[25]: array([1, 2, 3, 1, 2, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6, 7])

運行時測試-

In [62]: nv = np.random.randint(3, 10+1, size=(100000,))

In [63]: %timeit your_func(nv) # @MSeifert's solution
10 loops, best of 3: 129 ms per loop

In [64]: %timeit ranges(nv)
100 loops, best of 3: 5.54 ms per loop

除了使用numpy方法,您可以使用普通的python range s並將結果轉換為數組:

from itertools import chain
import numpy as np

def your_func(nv):
    ranges = (range(1, i+1) for i in nv)
    flattened = list(chain.from_iterable(ranges))
    return np.array(flattened)

這不需要利用難以理解的numpy切片和構造。 要顯示示例案例:

import random

>>> nv = [random.randint(1, 10) for _ in range(5)]
>>> print(nv)
[4, 2, 10, 5, 3]

>>> print(your_func(nv))
[ 1  2  3  4  1  2  1  2  3  4  5  6  7  8  9 10  1  2  3  4  5  1  2  3]

為什么要走兩步?

a = np.concatenate([np.arange(0,np.random.randint(3,11)) for i in range(1000000)])

暫無
暫無

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

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