How can I vectorize the interaction of two numpy arrays

huangapple go评论77阅读模式
英文:

How can I vectorize the interaction of two numpy arrays

问题

你的代码目前是针对较小的数组有效的。要向量化这个操作,你可以使用NumPy的高级功能来提高效率。以下是一个向量化的示例代码:

import numpy as np

# 输入数组a和b
a = np.array([[1, 0, 4, 5, 2, 3],
              [2, 3, 0, 1, 5, 4],
              [3, 4, 5, 0, 1, 2],
              [4, 5, 3, 2, 0, 1],
              [5, 2, 1, 4, 3, 0]])

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

# 创建一个与a相同形状的零数组c
c = np.zeros_like(a)

# 遍历数组b,执行相应的操作
for row in b:
    p, q, m1, m2 = row
    c[:, p] += a[:, q] * m1
    c[:, q] += a[:, p] * m2

# 打印结果数组c
print(c)

这个代码将对数组a和b进行向量化操作,生成与你所需的结果相符的数组c。

英文:

Consider two numpy arrays:

  1. array a: The important feature of array a is that every pair of columns (p and q) has a row that holds values (q and p) in that order.
    For example, columns 0 and 3 hold values 3 and 0 in row 2, and columns 4 and 5 hold values 5 and 4 in row 1.

    a = np.array([[1, 0, 4, 5, 2, 3],
                  [2, 3, 0, 1, 5, 4],
                  [3, 4, 5, 0, 1, 2],
                  [4, 5, 3, 2, 0, 1],
                  [5, 2, 1, 4, 3, 0]])
    
  2. array b: The first two columns show ALL column pairs (p and q) from array a. The remaining two columns are multipliers, as shown in the following: Consider array b's row 5 [1, 2, 4, -3]. We examine columns 1 and 2 of array a, and locate the values 2 and 1. Then we replace, in array a, the 2 by 2x4=8, and we replace the 1 by 1x(-3) = -3.

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

The final result would look like:

   c = np.array([[ 3, 0,-4,10, 0, 3],
                 [-2, 0, 0,-1, 5,-8],
                 [-6, 4,-5, 0,-2, 2],
                 [-4, 5, 3, 2, 0, 1],
                 [-5, 8,-3, 0, 0, 0]])       

Here is what I've been using. It works well for smaller arrays (produces the array c shown above), but my coding skills are quite rusty:

c = np.copy(a)

for brow in b:       
    arow = np.where(a[:, brow[0]] == brow[1])
    c[arow, brow[0]] = (a[arow, brow[0]])*brow[2]
    c[arow, brow[1]] = (a[arow, brow[1]])*brow[3]  
    
print(c)   

Could this be vectorized?

答案1

得分: 1

这是一个需要升维度的解决方案。让我们将您的代码定义在一个函数中,以便比较性能。

def find_c(a, b):
    c = np.copy(a)
    for brow in b:
        arow = np.where(a[:, brow[0]] == brow[1])
        c[arow, brow[0]] = (a[arow, brow[0]]) * brow[2]
        c[arow, brow[1]] = (a[arow, brow[1]]) * brow[3]
    return c

以及我编写了一些注释来解释我的解决方案:

def find_c_1(a, b):
    c = np.copy(a)
    # 升维度以索引数据
    array_find = a[:, None][:, 0, b[:, 0]].T
    # 找到与b[:, 1]的值对应的索引
    index = np.where(array_find == b[:, 1].reshape(-1, 1))

    # index[1]是行的索引,b[:, 0]是列的索引
    # 然后对值进行赋值
    c[index[1], b[:, 0]] = c[index[1], b[:, 0]] * b[:, 2]
    c[index[1], b[:, 1]] = c[index[1], b[:, 1]] * b[:, 3]
    return c

用于比较结果的部分:

c1 = find_c(a, b)
c2 = find_c_1(a, b)
print(np.array_equal(c1, c2))  # True

用于比较性能的部分:

%timeit find_c(a, b)
314 µs ± 5.92 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit find_c_1(a, b)
23.8 µs ± 1.06 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
英文:

Here is a solution which needs dimensionality ascension. Let's define your codes in a function for comparing the performance.

def find_c(a, b):
    c = np.copy(a)
    for brow in b:       
        arow = np.where(a[:, brow[0]] == brow[1])
        c[arow, brow[0]] = (a[arow, brow[0]])*brow[2]
        c[arow, brow[1]] = (a[arow, brow[1]])*brow[3] 
    return c

And my solution which I wrote some comments for explaining :

def find_c_1(a, b):
    c = np.copy(a)
    # ascension for indexing the data
    array_find = a[:, None][:, 0, b[:, 0]].T
    # find the index corresponds the values of b[:, 1] in array
    index = np.where(array_find == b[:, 1].reshape(-1, 1))
    
    # index[1] is the index of rows , b[:, 0] is the index of columns 
    # Then the assignment of the values
    c[index[1], b[:, 0]] = c[index[1], b[:, 0]] * b[:, 2]
    c[index[1], b[:, 1]] = c[index[1], b[:, 1]] * b[:, 3]
    return c

For comparing the result :

c1 = find_c(a, b)
c2 = find_c_1(a, b)
print(np.array_equal(c1, c2))  # True

For comparing the performance:

%timeit find_c(a, b)
314 µs ± 5.92 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit find_c_1(a, b)
23.8 µs ± 1.06 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

huangapple
  • 本文由 发表于 2023年7月3日 04:50:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/76600743.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定