使用numpy重复arange
我有一个包含整数值的数组。
a = [2,1,4,0,2]
我想对数组中的每个值应用一个叫做 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,但没有成功。
4 个回答
1
这段代码实现了你所描述的功能,也就是把所有中的值连接成一个范围。不过,这样做可能会导致你给的中出现一些错误:
>>> 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])]
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]
3
确实有更符合numpy风格的方法来处理这些事情。一个可能的方式可以是这样的:
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]]
如果你只是在拼接几个范围,那么可能Mr. E的纯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