【问题标题】:Set numpy matrix elements to zero if varying row index is exceeded如果超过不同的行索引,则将 numpy 矩阵元素设置为零
【发布时间】:2021-07-08 18:29:46
【问题描述】:

我有一个相当大的mn numpy 矩阵M 填充非零值和一个长度为m 的数组x,其中每个条目表示行索引,之后矩阵元素应该设置为零。所以例如,如果n=5x[i]=3,那么矩阵的第i行设置为[M_i1, M_i2, M_i3, 0, 0]

如果x 的所有条目都具有相同的值k,我可以简单地使用像M[:,k:]=0 这样的切片,但我无法找到一种有效的方法来处理每一行的不同值而不循环所有行并为每一行使用切片。

我想创建一个看起来像 [[1]*x[1] + [0]*(n-x[1]),...,[1]*x[m] + [0]*(n-x[m])] 的矩阵并将其用于布尔索引,但也不知道如何在不循环的情况下创建它。

非矢量化解决方案如下所示:

for i in range(m):
    if x[i] < n:
        M[i,x[i]:] = 0

示例输入

M = np.array([[1,2,3],[4,5,6]])
m, n =  2, 3
x = np.array([1,2])

和输出

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

有人有这个问题的矢量化解决方案吗?

非常感谢!

【问题讨论】:

  • 你好,发布非矢量化解决方案?
  • @ce.teuf 添加了它
  • 请贴出输入输出样例
  • 那么一些x 可能太大了?这些行不应该发生任何事情?
  • @hpaulj x 的最大值是 n,所以它只会发生它太大的值 1。

标签: python numpy matrix indexing vectorization


【解决方案1】:

您可以使用多维布尔索引:

M[x[:,None]<=np.arange(M.shape[1])] = 0

示例:

M = [[7, 8, 4, 2, 3, 9, 1, 8, 4, 3],
     [2, 1, 6, 1, 5, 2, 2, 2, 9, 2],
     [6, 1, 6, 8, 4, 3, 6, 9, 2, 6],
     [5, 4, 0, 8, 3, 0, 0, 1, 8, 7],
     [8, 7, 8, 8, 9, 2, 0, 8, 0, 2]]
x = [4, 4, 0, 6, 2]

输出:

      [[7, 8, 4, 2, 0, 0, 0, 0, 0, 0],
       [2, 1, 6, 1, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [5, 4, 0, 8, 3, 0, 0, 0, 0, 0],
       [8, 7, 0, 0, 0, 0, 0, 0, 0, 0]]

【讨论】:

  • x的元素之一设置为10或更多。还能用吗?
  • 我已经尝试过这种方法。它确实是矢量化的,但比使用 for 循环的“非矢量化”方法慢得多。问题是它隐式生成了一个 m × n 布尔矩阵,效率非常低。
  • @ShihaoXu。如果你做对了,那并不是非常低效的。时间是怎样的?我知道即使对于一个微不足道的数组,这也快了 1.5 倍,并且只会从那里变得更好
  • @MadPhysicist 我假设索引是有界的,但即使它大于界,它也应该工作。不应该吗?
  • @Ehsan。完全可以,因此赞成
【解决方案2】:

这看起来像是一个涂抹面具的练习。在每一行,你想从np.minimum(x[row], n)的元素开始涂抹:

mask = np.zeros(M.shape, bool)
mask[np.flatnonzero(x < n), x[x < n]] = True
M[np.cumsum(mask, axis=1, dtype=bool)] = 0

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-28
    • 1970-01-01
    相关资源
    最近更新 更多