[英]Multi-step linear algebra operations on multiple numpy arrays
我有3个numpy数组:
import numpy
arr_a = numpy.random.random((300, 300))
arr_b = numpy.random.random((300, 300))
arr_c = numpy.random.random((300, 300))
我想从3个数组的组合中创建第4个数组(arr_d)。 规则如下:
如果arr_a栅格像元值> 0.2和arr_b值<0.4且arr_c> 0.6,则用1填充arr_d
如果arr_a栅格像元值> 0.3且arr_b值<0.5且arr_c> 0.6,则用2填充arr_d
如果arr_a网格单元值> 0.1和arr_b值<0.2并且arr_c> 0.5,则用3填充arr_d
在所有其他情况下,用4填充arr_d
我可以使用嵌套循环来做到这一点,但这很慢,而且不是很pythonic。 另外,这是一个测试用例,实际数组的大小为1000 * 1000,所以我想要一个可扩展的解决方案,最好是可并行化的。
使用纯Python和for循环绝对不是走的路。 您可以使用NumPy中的数组操作编写程序,从而有效地在C中执行循环,从而极大地加快了代码的速度。 但是,这会为您的每个规则实例化一个全新的数组,每个规则的大小与数据的大小相同。 相反,您可以使用类似Numba的工具,例如Python的Anaconda发行版。 使用Numba,您可以使用循环来编写代码,而不会浪费时间(它将代码编译为本机机器指令)。 另外,不需要额外的大型阵列,从而使其存储效率比NumPy高得多。 Numba也碰巧更快,如以下示例所示:
import numpy, numba, time
def using_numpy(shape):
arr_a = numpy.random.random(shape)
arr_b = numpy.random.random(shape)
arr_c = numpy.random.random(shape)
mask1 = numpy.logical_and(numpy.logical_and((arr_a > 0.2), (arr_b < 0.4)), (arr_c > 0.6))
mask2 = numpy.logical_and(numpy.logical_and((arr_a > 0.3), (arr_b < 0.5)), (arr_c > 0.6))
mask3 = numpy.logical_and(numpy.logical_and((arr_a > 0.1), (arr_b < 0.2)), (arr_c > 0.5))
result = numpy.ones(arr_a.shape)*4
result[mask1] = 1
result[mask2] = 2
result[mask3] = 3
return result
@numba.jit
def using_numba(shape):
arr_a = numpy.random.random(shape)
arr_b = numpy.random.random(shape)
arr_c = numpy.random.random(shape)
result = numpy.empty(shape)
for i in range(result.shape[0]):
for j in range(result.shape[1]):
if arr_a[i, j] > 0.2 and arr_b[i, j] < 0.4 and arr_c[i, j] > 0.6:
result[i, j] = 1
elif arr_a[i, j] > 0.3 and arr_b[i, j] < 0.5 and arr_c[i, j] > 0.6:
result[i, j] = 2
elif arr_a[i, j] > 0.1 and arr_b[i, j] < 0.2 and arr_c[i, j] > 0.5:
result[i, j] = 3
else:
result[i, j] = 4
return result
# Compile the using_numba function
using_numba((0, 0))
t0 = time.time()
result = using_numpy((3000, 3000))
print('NumPy took', time.time() - t0, 'seconds')
t0 = time.time()
result = using_numba((3000, 3000))
print('Numba took', time.time() - t0, 'seconds')
在这里,我使用了(3000, 3000)
数组。 在我的机器上,使用NumPy需要0.47秒,而使用Numba需要0.29秒。
一种方法是使用布尔映射
condition_1 = numpy.logical_and(numpy.logical_and((arr_a > 0.2), (arr_b < 0.4)), (arr_c > 0.6))
condition_2 = numpy.logical_and(numpy.logical_and((arr_a > 0.3), (arr_b < 0.5)), (arr_c > 0.6))
condition_3 = numpy.logical_and(numpy.logical_and((arr_a > 0.1), (arr_b < 0.2)), (arr_c > 0.5))
result = numpy.ones((300, 300)) * 4
result[numpy.where(condition_3)] = 3
result[numpy.where(condition_2)] = 2
result[numpy.where(condition_1)] = 1
它避免了嵌套循环,但分配了三个专用数组,并进行了大量多余的分配。 必须有一个更优化的方法...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.