Python 如何优化numpy循环,该循环对由另一个数组索引的数组中的值求和,其中值等于循环索引
我有一段代码,在应用程序运行期间被多次调用。 它采用一个表示值的数字数组(value\u数组)。 这些应汇总到区域中,这些区域在区域数组中定义。 zone_ID表示zone_数组中所有可能区域的列表 基本上是这样的:我有一张人口栅格地图,我想知道每个分区地图上有多少人 守则:Python 如何优化numpy循环,该循环对由另一个数组索引的数组中的值求和,其中值等于循环索引,python,performance,numpy,for-loop,Python,Performance,Numpy,For Loop,我有一段代码,在应用程序运行期间被多次调用。 它采用一个表示值的数字数组(value\u数组)。 这些应汇总到区域中,这些区域在区域数组中定义。 zone_ID表示zone_数组中所有可能区域的列表 基本上是这样的:我有一张人口栅格地图,我想知道每个分区地图上有多少人 守则: values = np.zeros(len(zone_ids)) for i in zone_ids: values[i] = round(np.nansum(value_array[zone_array == i
values = np.zeros(len(zone_ids))
for i in zone_ids:
values[i] = round(np.nansum(value_array[zone_array == i]), 2)
return values
罪魁祸首似乎是for循环,但我没有找到消除它的方法,也没有得到相同的结果
我试着用bincount,但没有成功。
使用numba jit也没有效果
我想远离cython,因为这段代码将用于Qgis插件中,该插件不支持cython
测试代码:
import numpy as np
def fill_values(zone_array, value_array, zone_ids):
values = np.zeros(len(zone_ids))
for i in zone_ids:
values[i] = round(np.nansum(value_array[zone_array == i]), 2)
return values
def run():
# 300 different zones
zone_ids = range(300)
# zone map with 300 zones
zone_array = (np.random.rand(2000, 2000) * 300).astype(int)
# value map from which we want the sum of values per zone (real map can have NaN values)
value_array = (np.random.rand(2000, 2000) * 10.)
value_array[5, 5] = np.NAN
fill_values(zone_array, value_array, zone_ids)
if __name__ == '__main__':
run()
每个回路1.92 s±17.5 ms(7次运行的平均值±标准偏差,每个回路1次)
按照Divakar的建议实施bincount:
每个循环203 ms±15.2 ms(7次运行的平均值±标准偏差,每个循环1次)如果直接使用
bincount
,则总和中会有NaNs
。因此,您只需将NaNs
替换为zero
,并使用bincount
。作为矢量化解决方案,这应该快得多
因此,实施将是必要的-
val_nonan = np.where(np.isnan(value_array), 0, value_array)
out = np.round(np.bincount(zone_array.ravel(), val_nonan.ravel()),2)
罪魁祸首不是for循环。相反,问题在于内部的比较
zone\u array==i
。必须检查每个分区的所有2000x2000=4e6值是否等于i
。如果我减少分区id的数量,我将获得速度提升,因此for循环仍然涉及性能问题。因为我知道我没有选择不做zone\u array==i
的方法,所以我专注于循环。最好的方法是我可以使用zone\u array==zone\u ids
跳过循环。您可以广播与zone\u array[:,:,None]==zone\u ids
的比较,但这仍然将索引保留在for循环中,并且不会给性能带来太多改善。这解决了我的问题。谢谢。我猜我的bincount会尝试被nan值搞砸的地方。另外,values=out[zone_id]
用于需要分区子集结果的情况。