我有一个包含地球物理数据的大矩阵(形状:2e6,6)。在搜索矩阵中的值以分配变量之前,我有3个for
循环。
我的第一个解决方案是np.where
。这太慢了!我阅读it would be better以使用另一个for
循环来提高性能。但是,我提出的代码甚至略慢。
有人知道如何提高性能吗?
第一个解决方案(np.where
)
for lat in LATS:
for lon in LONS:
for depth in range(1,401,1):
node_point_line = matrix[np.where( (matrix[:,0]==lat) * (matrix[:,1]==lon) * (matrix[:,2]==depth) )][0]
var1 = node_point_line[3]
var2 = node_point_line[4]
var3 = node_point_line[5]
...
第二个解决方案(额外for
循环)
for lat in LATS:
for lon in LONS:
for depth in range(1,401,1):
matrix_flat = matrix.flatten()
for i in range( len( matrix_flat )):
if matrix_flat[i]==lat and matrix_flat[i+1]==lon and matrix_flat[i+2]==depth:
var1 = matrix_flat[i+3]
var2 = matrix_flat[i+4]
var3 = matrix_flat[i+5]
...
同样,两种解决方案都太慢了。我避免使用Fortran或C ++(我知道它更快)。有什么建议吗?
答案 0 :(得分:0)
您的LATS
和LONS
数组有多大?即使它们是一个元素长,那么你的程序必须执行大约1*1*400*1e6*3 ~ 1.2e9
个操作,这太过分了。即使在C ++中正确实现,也可能需要一秒或更长时间。
我认为你应该优化你的算法。目前还不是很清楚你要做什么,但我的猜测是你试图找到一个矩阵中的任何位置,该矩阵在LATS
列表中有纬度,经度在LONS
列表中深度在1到400之间。循环的交换位置:沿外循环中的矩阵运行,然后检查所有三个条件是否成立。之后,您将能够用set
纬度替换纬度列表,set
查找比列表查找快得多。
答案 1 :(得分:0)
考虑到数字,只需lexsort
数据阵列就可以合理有效。在开头删除所有where
语句时投入了2秒。
代码段假定LATS
和LONS
已排序:
order = np.lexsort([matrix.T][2::-1] # takes < 2 sec
sorted = matrix[order, :]
data_per_lat = np.split(sorted, sorted[:, 0].searchsorted(LATS[1:], axis=0)
for lat, dpla in zip(LATS, data_per_lat):
data_per_lon = np.split(dpla, dpla[:, 1].searchsorted[LONS[1:], axis=0)
for lon, dplo in zip(LONS, data_per_lon):
depth, var1, var2, var3 = dplo.T[2:]
# the variables are now vectors, containing all data matching lon and lat sorted by depth
答案 2 :(得分:0)
您可以使用矢量化过程压缩起始矩阵,这将使您的循环更快。
DPTH=np.arange(1,401,1)
mask=np.in1d(matrix[:,0],LATS) * np.in1d(matrix[:,1],LONS) * np.in1d(matrix[:,2],DPTH)
matrix_masked=matrix[mask]
然后只需for
通过matrix_masked
(复杂)或
nditer
for i in range(matrix_masked.shape[0]):
var1 = matrix_masked[i,3]
. . .