我正在寻找一种在Numpy中使用列表推导方法或类似方法来消除使用for循环的方式。例如,index_values是一个Python字典列表,其中包含各种不同长度的索引值列表,而s是一个numpy向量:
有没有一种方法可以消除 for 循环?
for i in range(33):
s[index_values[i]] += 4.1
有没有一种方法可以消除 for 循环?
for i in range(33):
s[index_values[i]] += 4.1
我不完全理解index_values
是什么类型的对象。但如果它是一个ndarray
,或者可以转换成一个ndarray
,那么您只需这样做:
>>> s = numpy.arange(20)
>>> index_values = (numpy.random.random((3, 3)) * 20).astype('i')
>>> s[index_values] = 4
>>> s
array([ 0, 1, 4, 4, 4, 5, 6, 4, 8, 4, 4, 11, 12,
13, 4, 15, 4, 4, 4, 19])
编辑:但在这种情况下似乎行不通。根据您的编辑和评论,我想出了一种可能适合您的方法。一个随机的列表,其中包含长度不同的子列表...
>>> index_values = [list(range(x, x + random.randrange(1, 5)))
... for x in [random.randrange(0,50) for y in range(33)]]
把它转换成数组并不难:
>>> index_value_array = numpy.fromiter(itertools.chain(*index_values),
dtype='i')
如果您知道数组的长度,请指定 count
以获得更好的性能:
>>> index_value_array = numpy.fromiter(itertools.chain(*index_values),
dtype='i', count=83)
由于您的编辑表明您想要类似直方图的行为,因此简单的索引将不起作用,正如Robert Kern所指出的那样。所以请使用numpy.histogram
:
>>> hist = numpy.histogram(index_value_array, bins=range(0, 51))
直方图
通常用于浮点数的统计,这意味着bin大小必须稍微大一些,因为最后一个值包含在最后一个bin中。因此,如果我们使用更直观的range(0, 50)
,则48和49将位于同一个bin中。结果是一个元组,其中包含一个长度为n的计数数组和一个长度为n + 1的bin边界数组:
>>> hist
(array([2, 2, 1, 2, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 5, 5, 5, 3, 3,
3, 3, 3, 2, 1, 0, 2, 3, 3, 1, 0, 2, 3, 2, 2, 2, 3, 2, 1, 1, 2, 2,
2, 0, 0, 0, 1, 0]),
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50]))
>>> s = numpy.arange(50, dtype='f')
>>> hist[0] * 4.1 + s
array([ 8.2, 9.2, 6.1, 11.2, 8.1, 5. , 6. , 7. , 12.1,
13.1, 14.1, 15.1, 16.1, 13. , 18.1, 19.1, 20.1, 37.5,
38.5, 39.5, 32.3, 33.3, 34.3, 35.3, 36.3, 33.2, 30.1,
27. , 36.2, 41.3, 42.3, 35.1, 32. , 41.2, 46.3, 43.2,
44.2, 45.2, 50.3, 47.2, 44.1, 45.1, 50.2, 51.2, 52.2,
45. , 46. , 47. , 52.1, 49. ])
我不知道这是否符合您的需求,但这似乎是一个不错的方法,而且应该以接近 c 的速度运行,因为它只使用了 numpy
和 itertools
。
index_values
中存在重复时,增强赋值不会像在完整的for循环中那样重复发生(原因比较复杂)。因此,您不能使用这种类型的索引来执行特定的直方图操作,尽管许多人尝试这样做。 - Robert Kernnumpy.array
,以生成相应形状的ndarray
,如下所示:numpy.array([[1, 2, 3], [1, 2, 3]])
。如果你必须使用一个字典,你至少可以通过以下方式获得一些速度:numpy.array([d[i] for i in range(2)])
。 - senderle这个怎么样:
s[reduce(lambda x,y: x+y, [index_values[x] for x in range(33)], [])] = 4.1
s
的某些部分,而不是创建一个新数组 :) - Ricardo Cárdenes