在2d numpy数组的每一行中找到最小非零值

4

我试图寻找2D numpy数组中每行最小的非零值,但是一直没有找到优雅的解决方案。 我查看了一些其他帖子,但没有一个解决完全相同的问题,例如在2D数组中找到最小值在1D数组中排除零的最小/最大值

例如给定以下数组:
x = np.array([[3., 2., 0., 1., 6.], [8., 4., 5., 0., 6.], [0., 7., 2., 5., 0.]])

答案如下:
[1., 4., 2.]

1
这个回答解决了你的问题吗?在numpy数组中查找沿轴排除零的最小/最大值 - mkrieger1
4个回答

6
一种方法是将零重新分配为np.inf,然后对每行进行最小值计算:
np.where(x>0, x, np.inf).min(axis=1)

输出:

array([1., 4., 2.])

@ScottBoston,你的回答太棒了!!!太喜欢了。我不知道np可以这样做,最好的部分是x仍然完好无损。 - Joe Ferndz

4

遮盖数组正是为此类目的而设计的。您可以利用从数组中屏蔽掉的零(或任何其他类型的掩码),并且现在可以对您的遮盖数组执行几乎所有正常数组上的操作:

import numpy.ma as ma
mx = ma.masked_array(x, mask=x==0)
mx.min(1)

输出:

[1.0 4.0 2.0]

1
# example data
x = np.array([[3., 2., 0., 1., 6.], [8., 4., 5., 0., 6.], [0., 7., 2., 5., 0.]])

# set all the values inside the maxtrix which are equal to 0, to *inf*
# np.inf represents a very large number
# inf, stands for infinity
x[x==0] = np.inf

# grep the lowest value, in each array (now that there is no 0 value anymore)
np.min(x, axis=1)

如果您解释一下您提供的代码是如何回答问题的话,这将会是一个更好的答案。 - pppery
我理解逻辑,但不确定这样做的效率如何。此外,如果我不想用inf替换零,则必须创建x的新副本。 - Usman Tariq
1
@UsmanTariq - 在这个矩阵 x = np.random.randint(low = 0, high=5, size=( 10**7 ,5)) 上,它需要497毫秒,所以我认为它会运行得很好 :) np.where 稍微慢一点.. 需要793毫秒。而 ma.masked_array 是最快的,只需要121毫秒。 - Dieter

1

我用的解决方法时间复杂度为o(n^2)

import numpy as np
x = np.array([[3., 2., 0., 1., 6.], [8., 4., 5., 0., 6.], [0., 7., 2., 5., 0.]])

for i in range(len(x)) :
    small=x[i][i]
    for j in x[i] :
        if (j!=0 and j<small):
            small=j
    print(small)

2
虽然努力了,但速度会非常慢。如果你正在使用向量(数组),尽可能避免使用循环。 - Dieter
@Dieter 是的,没错。我们的主要逻辑是一样的!但我写了我脑海中最简单的方法。 - mo1ein
你为什么认为你的解决方案是O(n^2)?-并不是因为你使用了两个for循环,就代表它是n^2。 - Dieter
有道理。但这是太多样板代码,我想避免并以更具 Python 风格的方式完成。此外,当您说复杂度为n^2时,您假定n是多少? - Usman Tariq
是的,这是n的平方,我犯了一个错误。我知道这种方法不快,但我认为可能会有帮助。 - mo1ein

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接