首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何通过矩阵numpy向量化循环

如何通过矩阵numpy向量化循环
EN

Stack Overflow用户
提问于 2019-06-25 23:49:20
回答 2查看 1.5K关注 0票数 6
import numpy as np

mat = np.random.randint(2, size=(100000,100))

我希望遍历这个矩阵,如果每个row完全包含1或0,我希望将state变量更改为该值。state的初始值为0。

state = 0

for row in mat:
    if set(row) == {1}:
        state = 1
    elif set(row) == {0}:
        state = 0
    else:
        row[:] = state

谁能告诉我如何利用numpy来向量化这个循环并加速它?

因此,对于示例输入

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

在这种情况下,预期输出将是

array([[0, 0, 0],
       [0, 0, 0],
       [1, 1, 1],
       [1, 1, 1],
       [1, 1, 1]])
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-06-26 08:33:35

下面是一个简单快速的numpy方法:

import numpy as np

def pp():
    m,n = a.shape
    A = a.sum(axis=1)    
    A = np.where((A==0)|(A==n))[0]
    if not A.size:
        return np.ones_like(a) if state else np.zeros_like(a)
    st = np.concatenate([np.arange(A[0]!=0), A, [m]])
    v = a[st[:-1],0]
    if A[0]:
        v[0] = state
    return np.broadcast_to(v.repeat(st[1:]-st[:-1])[:,None],(m,n))

我用这个做了一些计时

state=0
a = (np.random.random((100000,100))<np.random.random((100000,1))).astype(int)

简单的测试用例:

0.8655898020006134   # me
4.089095343002555    # Alain T.
2.2958932030014694   # Divakar 1
2.2178015549980046   # & 2
票数 0
EN

Stack Overflow用户

发布于 2019-06-26 02:37:58

通过利用np.accumulate,您可以在没有任何循环的情况下完成此操作

R = 5 # 100000
C = 3 # 100

mat   = np.random.randint(2, size=(R,C))
print(mat) # original matrix

state    = np.zeros((1,C))                        # or np.ones((1,C))
mat      = np.concatenate([state,mat])            # insert state row
zRows    = np.isin(np.sum(mat,1),[0,C])           # all zeroes or all ones
iRows    = np.arange(R+1) * zRows.astype(np.int)  # base indexes
mat      = mat[np.maximum.accumulate(iRows)][1:]  # indirection, remove state
print(mat) # modified

#original
[[0 0 1]
 [1 1 1]
 [1 0 1]
 [0 0 0]
 [1 0 1]]

# modified
[[0 0 0]
 [1 1 1]
 [1 1 1]
 [0 0 0]
 [0 0 0]]

它的工作方式是为需要更改的行准备一个间接数组。这是通过行索引的np.arange完成的,其中我们将需要替换的索引设置为零。累积最大索引会将每个被替换的行映射到它之前的全零或全一行。

例如:

  [ 0, 1, 2, 3, 4, 5 ] # row indexes
  [ 0, 1, 0, 0, 1, 0 ] # rows that are all zeroes or all ones (zRows)
  [ 0, 1, 0, 0, 4, 0 ] # multiplied (iRows)
  [ 0, 1, 1, 1, 4, 4 ] # np.maximum.accumulate

这为我们提供了一个索引列表,其中的行内容应该从中获取。

状态由在执行操作之前在矩阵开始处插入的额外行表示,在执行操作后删除。

这个解决方案对于非常小的矩阵(5x3)会稍微慢一些,但对于较大的矩阵(100000x100: 0.7秒对14秒),它可以让您的速度提高20倍。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56757804

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档