我有一个Numpy矩阵,我使用for循环遍历矩阵中的每一行,我想从每行中找到第一个非零值
我已经找到了一种方法来找到这里的第一个非零值,但它需要一个列表作为参数:
for row in matrix:
val = next((i for i, x in enumerate(row) if x), None)
它总是为val返回0
我还尝试在计算'val'之前将行转换为列表
rowList = row.tolist()
但这也返回了相同的值
当我打印任何一个值时,输出在列表周围包含2个括号,也许这有影响?
即。
[[0, 0, 1, 2, 3]]
即使在将行转换为列表之后,也会发生这种情况
有没有什么方法可以将每一行转换为一个列表,这样我就可以找到第一个非零值的索引,或者有没有其他更简单的方法来做到这一点?
3条答案
按热度按时间sigwle7e1#
您的
next
表达式工作:好的,这给出了第一个非零值的索引,但在我的示例中,它比
1
值更有趣。但如果数组中有一行全为0,例如在
nonzero
版本引发错误。它需要对nonzero
返回空列表的情况敏感。要从
idx
列表中获取值,请使用计时
对于大型对角阵列,
nonzero
的速度要快得多:对于相同大小的数组,所有1都在行的前面,
next
方法稍微快一些。Python中的短路循环和C代码中的全循环之间有一个折衷。
argmax
是另一种查找每行中第一个非零索引的方法:使用轴参数时,
argmax
必须逐行迭代,然后在行内迭代,但它在编译代码中这样做。使用这样的布尔参数,argmax
会短路。我在另一个关于argmax
(或min)和nan
值的问题中探讨了这一点,这也是短路。https://stackoverflow.com/a/41324751/901925
另一种可能性(通道
@Divakar
?)wooyq4lh2#
你不需要“将numpy数组转换为列表”,你需要一种更好的方法来查找非零元素。使用
nonzero
:返回非零元素的索引。
例如:
或者:
af7jpaap3#
我的猜测是,像你之前的许多人一样,包括我自己,你被
np.matrix
类绊倒了。此类的切片示例会产生意外结果:
正如你所怀疑的,这可能也是你的发电机技巧不起作用的原因。迭代
np.matrix
中的一行将一次返回整行,然后停止。如果出于某种原因,你正在处理一个矩阵,但希望它像一个数组一样,你可以使用
.A
属性。最后一句话:
**请勿在此处将行转换为列表!**您使用的生成器技巧的目的是尽快停止搜索。假设你的行有100,000个元素,每个元素都是非零的。生成器将查看前几个,一旦找到第一个非零值(几乎肯定在前50个范围内),它将跳过行的其余部分(> 99,950)。如果你转换成list,你就把这种节省扔掉了,因为要生成等价的list,每个元素都必须被读取。这也是为什么在这种情况下生成器可以与向量化的numpy函数竞争的原因。