2013-02-26 79 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