如何将包含索引的函数矢量化为变量

时间:2018-02-11 23:05:40

标签: python arrays numpy vectorization

NumPy(1.10)是否可以将包含索引的函数矢量化为变量? 我有一个bool数组A(i,j,k)和第二个数组B(bool和3 d,也是更大),其中元素应该根据某些条件得到它的状态,简化:

if A[i][j][k] == True:
    B[i+1][j][k] = True
    B[i][j+1][k] = True
    B[i][j][k+1] = True

(因此对于A中的每个元素都是True,B中与每个方向上原始位置+1步距的元素都设置为true)

我感觉我无法避免嵌套循环,但我想(数组很大,执行时间很重要),我会很高兴提示如何实现这一点。 (如果问题是noobish,请关注我,我是初学者。)

2 个答案:

答案 0 :(得分:0)

这适用于2D矩阵:

import numpy as np
from scipy import signal

A = (np.random.normal(0, 1, 64) > 1).reshape(8, 8)
k = np.array([[0, 0, 0], [0, 0, 1], [0, 1, 0]])
B = np.minimum(signal.convolve2d(A, k, mode='same'), 1)

给出:

>>> A
array([[0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 1, 0, 0, 0],
       [0, 0, 0, 1, 0, 0, 0, 0],
       [0, 1, 0, 0, 0, 1, 0, 0],
       [0, 0, 1, 0, 0, 1, 0, 0],
       [1, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 1, 1, 0]])

>>> B
array([[0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 1, 0, 0],
       [0, 0, 0, 0, 1, 0, 0, 0],
       [0, 0, 1, 1, 0, 0, 1, 0],
       [0, 1, 0, 1, 0, 1, 1, 0],
       [0, 1, 1, 0, 0, 1, 0, 0],
       [1, 0, 0, 0, 0, 0, 1, 1]])

对于N-D矩阵,可以类似地扩展它。

from scipy import ndimage

A = (np.random.normal(0, 1, 64) > 1).reshape(8, 8)
k = np.array([
    [[0, 0, 0], [0, 1, 0], [0, 0, 0]],
    [[0, 1, 0], [1, 0, 0], [0, 0, 0]],
    [[0, 0, 0], [0, 0, 0], [0, 0, 0]]])
B = np.minimum(ndimage.correlate(A, k, mode='constant'), 1)

给出:

>>> A
array([[[0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]],

       [[0, 0, 0, 0],
        [1, 0, 0, 0],
        [0, 0, 0, 1],
        [0, 0, 0, 0]],

       [[0, 1, 0, 0],
        [0, 1, 0, 0],
        [0, 0, 1, 0],
        [0, 1, 0, 0]],

       [[1, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 1, 1, 0]]])

>>> B
array([[[0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]],

       [[0, 0, 0, 0],
        [0, 1, 0, 0],
        [1, 0, 0, 0],
        [0, 0, 0, 1]],

       [[0, 0, 1, 0],
        [1, 1, 1, 0],
        [0, 1, 0, 1],
        [0, 0, 1, 0]],

       [[0, 1, 0, 0],
        [1, 1, 0, 0],
        [0, 0, 1, 0],
        [0, 1, 1, 1]]])

完成!

验证上述代码正确性的简单方法是在这样的矩阵上运行它:

A = np.zeros((4, 4, 4), int)
A[0, 1, 2] = 1

这会产生预期的结果:

>>> A
array([[[0, 0, 0, 0],
        [0, 0, 1, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]],

       [[0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]],

       [[0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]],

       [[0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]]])

>>> B
array([[[0, 0, 0, 0],
        [0, 0, 0, 1],
        [0, 0, 1, 0],
        [0, 0, 0, 0]],

       [[0, 0, 0, 0],
        [0, 0, 1, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]],

       [[0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]],

       [[0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]]])

答案 1 :(得分:0)

我怀疑你已经将问题简化了一些,但正如所说的那样,它可以通过生成所有维度的变换来解决,然后或者所有的一起:

import numpy as np

# Test data
A = np.zeros([3,5,2], dtype=bool)
A[0,2,1] = True
A[1,4,1] = True

# Generate bigger result matrices
i,j,k = A.shape
B0 = np.zeros([i+1,j+1,k+1], dtype=bool)
B1 = np.zeros([i+1,j+1,k+1], dtype=bool)
B2 = np.zeros([i+1,j+1,k+1], dtype=bool)

# Get partial answers by offsetting A
B0[1:,:-1,:-1] = A
B1[:-1,1:,:-1] = A
B2[:-1,:-1,1:] = A

# Combine answers by oring together parts
B = B0 | B1 | B2

我担心这不完全是你想要的。