2013-02-26 78 views
2

我有一個整數值的數組。重複與numpy的範圍

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

我想要一個應用人氣指數函數的每個值在以具有:

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

事實上,我使用np.repeat函數根據陣列的重複陣列的行,並且我希望我有一個標記,將每個重複值與原始值相關聯,並有一個識別號碼以便區分它們。

我試過用np.vectorize但沒有成功。

+2

您能否展示一些更多的代碼 - 您從a到b的確切程度如何?最重要的是,[你有什麼嘗試?](http://whathaveyoutried.com) – 2013-02-26 12:38:10

回答

3

肯定有更多的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]] 

如果您串聯只有幾個範圍,那麼很可能鄂先生的純Python的解決方案是您最好的選擇,但如果你有即使僅有百範圍來連接,這顆恆星明顯更快。爲了比較我用從其他的答案中提取這兩個功能:

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 
+0

有趣的看到時代。謝謝。 – YXD 2013-02-27 16:24:28

+0

+1,我喜歡用基準測試的答案!而且我必須研究這個'as_strided'函數,它令我困惑。 – Junuxx 2013-02-27 16:42:27

+1

@Junuxx這是那種讓人難以抗拒的小塊狀的東西之一。 [這些要點](https://gist.github.com/seberg)來自numpy wiz [seberg](http://stackoverflow.com/users/455221/seberg)有一些很好的例子。 – Jaime 2013-02-27 17:24:51

1

這就是你好像要描述的,即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,]) 

後您的編輯,說明您想aranges的名單,我認爲這將是更有效的:

>>> 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])] 
+0

當我從Python開始時,擁有不同的解決方案總是很好的。這將有助於未來的問題。我只是提到Junuxx的解決方案似乎比E先生的解決方案快。 – Alexis 2013-02-26 13:10:11

2

我的回答類似於Junuxx - 我不知道你給b的答案是一個你想

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

給我

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

另一個不一致之處在於問題標題和標籤提到了Numpy,但該示例顯示了列表。你的代碼可以在列表上工作,但不能在Numpy數組上運行(加上陣列不會追加,而是添加向量) – Junuxx 2013-02-26 12:53:57

+0

這是真的。我認爲它提到'np.repeat',因爲它與期望的行爲密切相關,而不是一個特定的問題 – YXD 2013-02-26 12:56:09

+0

Oups,對於錯誤感到抱歉,謝謝你的回答 – Alexis 2013-02-26 13:03:59

0

另一種方式,是在一般的存取效率更高,而且稍快:

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