Python 基于位置向量的元素聚合

Python 基于位置向量的元素聚合,python,numpy,vectorization,Python,Numpy,Vectorization,我试图将一个非常简单的操作矢量化,但似乎不知道如何实现 给定一个非常大的数值向量(超过1M个位置)和另一个大小为n的数组,以及一组给定的位置,我想得到一个大小为n的向量,元素是第二个向量指定的第一个向量值的平均值 a = np.array([1,2,3,4,5,6,7]) b = np.array([[0,1],[2],[3,5],[4,6]]) c = [1.5,3,5,6] 我需要多次重复此操作,因此性能是一个问题 香草python解决方案: import numpy as np imp

我试图将一个非常简单的操作矢量化,但似乎不知道如何实现

给定一个非常大的数值向量(超过1M个位置)和另一个大小为n的数组,以及一组给定的位置,我想得到一个大小为n的向量,元素是第二个向量指定的第一个向量值的平均值

a = np.array([1,2,3,4,5,6,7])
b = np.array([[0,1],[2],[3,5],[4,6]])

c = [1.5,3,5,6]
我需要多次重复此操作,因此性能是一个问题

香草python解决方案:

import numpy as np
import time

a = np.array([1,2,3,4,5,6,7])
b = np.array([[0,1],[2],[3,5],[4,6]])

begin = time.time()

for i in range(100000):

    c = []

    for d in b:
        c.append(np.mean(a[d]))

print(time.time() - begin, c)
# 3.7529971599578857 [1.5, 3.0, 5.0, 6.0]

我不确定这是否一定更快,但您不妨尝试:

import numpy as np

a = np.array([1, 2, 3, 4, 5, 6, 7])
b = np.array([[0, 1], [2], [3, 5], [4, 6]])

# Get the length of each subset of indices
lens = np.fromiter((len(bi) for bi in b), count=len(b), dtype=np.int32)
# Compute reduction indices
reduce_idx = np.roll(np.cumsum(lens), 1)
reduce_idx[0] = 0
# Make flattened array of index lists
idx = np.fromiter((i for bi in b for i in bi), count=lens.sum(), dtype=np.int32)
# Reorder according to indices
a2 = a[idx]
# Sum reordered array at reduction indices and divide by number of indices
c = np.add.reduceat(a2, reduce_idx) / lens
print(c)
# [1.5 3.  5.  6. ]

np.fromiter(map(lambda i:a[i].mean(),b),np.float)
是一种简单的方法。也许有一些更有效的
numpy
方法我错过了!看起来是一个方便的函数,但是它的执行速度似乎并不比普通的python实现快。那么,
a
很大,但是
b
也很大吗?一种解决方案是迭代
b
,对
a
使用奇特的索引,然后对索引结果调用mean。这是您的“香草python”解决方案吗?例如
[a[inds].mean()对于b中的inds]
b中的位置是否总是顺序的?也就是说,你是否总是计算<代码> A/<代码>的连续切片的平均值,或者在<代码> B <代码>中的索引可以是任意顺序的,还是可以重复的?关于<代码> Frutmer-<代码>,可以使用,但是考虑传递<代码>计数=LeN(b)< /代码>效率。在i范围内(LeN(b)):比C代码快25%(C.AppEnter)(NP [MaMean(A[B[i]))
,这还不错,但我希望有更大的改进(我指的是运行速度至少比简单的python循环快10倍的东西)@Sovos如果用索引整数的平面数组和每个子列表大小的另一个数组替换列表数组,您可以获得这种加速(也就是说,如果您在上述代码中相应地输入
idx
lens
)。我不知道您从何处获取数据,但如果您可以用它更改数组段的编码,那么在我的解决方案中跳过这两个步骤会使速度加快10倍以上。对不起,您完全正确。这很有帮助,谢谢!