How can I vectorize the interaction of two numpy arrays

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

How can I vectorize the interaction of two numpy arrays

问题

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

  1. import numpy as np
  2. # 输入数组a和b
  3. a = np.array([[1, 0, 4, 5, 2, 3],
  4. [2, 3, 0, 1, 5, 4],
  5. [3, 4, 5, 0, 1, 2],
  6. [4, 5, 3, 2, 0, 1],
  7. [5, 2, 1, 4, 3, 0]])
  8. b = np.array([[0, 1, 3, -1],
  9. [0, 2, -1, 3],
  10. [0, 3, -2, 4],
  11. [0, 4, -1, 0],
  12. [0, 5, -1, 4],
  13. [1, 2, 4, -3],
  14. [1, 3, 0, -1],
  15. [1, 4, 1, -2],
  16. [1, 5, 1, 1],
  17. [2, 3, 1, 1],
  18. [2, 4, -1, 0],
  19. [2, 5, -1, 1],
  20. [3, 4, 0, 0],
  21. [3, 5, 2, 1],
  22. [4, 5, 1, -2]])
  23. # 创建一个与a相同形状的零数组c
  24. c = np.zeros_like(a)
  25. # 遍历数组b,执行相应的操作
  26. for row in b:
  27. p, q, m1, m2 = row
  28. c[:, p] += a[:, q] * m1
  29. c[:, q] += a[:, p] * m2
  30. # 打印结果数组c
  31. 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.

    1. a = np.array([[1, 0, 4, 5, 2, 3],
    2. [2, 3, 0, 1, 5, 4],
    3. [3, 4, 5, 0, 1, 2],
    4. [4, 5, 3, 2, 0, 1],
    5. [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.

    1. b = np.array([[0, 1, 3 -1],
    2. [0, 2, -1, 3],
    3. [0, 3, -2, 4],
    4. [0, 4, -1, 0],
    5. [0, 5, -1, 4],
    6. [1, 2, 4, -3],
    7. [1, 3, 0, -1],
    8. [1, 4, 1, -2],
    9. [1, 5, 1, 1],
    10. [2, 3, 1, 1],
    11. [2, 4, -1, 0],
    12. [2, 5, -1, 1],
    13. [3, 4, 0, 0],
    14. [3, 5, 2, 1],
    15. [4, 5, 1, -2]])

The final result would look like:

  1. c = np.array([[ 3, 0,-4,10, 0, 3],
  2. [-2, 0, 0,-1, 5,-8],
  3. [-6, 4,-5, 0,-2, 2],
  4. [-4, 5, 3, 2, 0, 1],
  5. [-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:

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

Could this be vectorized?

答案1

得分: 1

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

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

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

  1. def find_c_1(a, b):
  2. c = np.copy(a)
  3. # 升维度以索引数据
  4. array_find = a[:, None][:, 0, b[:, 0]].T
  5. # 找到与b[:, 1]的值对应的索引
  6. index = np.where(array_find == b[:, 1].reshape(-1, 1))
  7. # index[1]是行的索引,b[:, 0]是列的索引
  8. # 然后对值进行赋值
  9. c[index[1], b[:, 0]] = c[index[1], b[:, 0]] * b[:, 2]
  10. c[index[1], b[:, 1]] = c[index[1], b[:, 1]] * b[:, 3]
  11. return c

用于比较结果的部分:

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

用于比较性能的部分:

  1. %timeit find_c(a, b)
  2. 314 µs ± 5.92 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
  3. %timeit find_c_1(a, b)
  4. 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.

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

And my solution which I wrote some comments for explaining :

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

For comparing the result :

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

For comparing the performance:

  1. %timeit find_c(a, b)
  2. 314 µs ± 5.92 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
  3. %timeit find_c_1(a, b)
  4. 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:

确定