如何将 Numpy 格式的列表转换为 python
How to convert lists in Numpy format to python
我有一个 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]]
即使在我将行转换为列表后也会出现这种情况
有没有什么方法可以将每一行转换为一个列表,这样我就可以找到第一个非零值的索引,或者是否有另一种更简单的方法来做到这一点?
您不需要 "convert a numpy array to list",您需要更好的方法来查找 non-zero 元素。为此你应该使用 nonzero
:
Return the indices of the elements that are non-zero.
诸如此类:
import numpy as np
arr = np.array([0, 0, 9, 2])
print(arr[arr.nonzero()][0])
# 9
或者:
import numpy as np
matrix = np.array([[0, 0, 9, 2], [0, 3, 0, 1]])
for row in matrix:
print(row[row.nonzero()][0])
# 9
# 3
我的猜测是,与包括我在内的许多其他人一样,您被 np.matrix
class.
绊倒了
切片此 class 的实例会产生意外结果:
>> id = np.identity(4)
>>> type(id)
<class 'numpy.ndarray'>
>>> id[2]
array([ 0., 0., 1., 0.]) # shape == (4,)
>>> id_m = np.matrix(id)
>> type(id_m)
<class 'numpy.matrixlib.defmatrix.matrix'>
>>> id_m[2]
matrix([[ 0., 0., 1., 0.]]) # shape == (4, 1)
如您所料,这可能也是您的生成器技巧不起作用的原因。
迭代一行 np.matrix
会因为它一次性嵌套了 return 整行然后停止。
如果出于某种原因您正在处理一个矩阵,但希望它表现得像一个数组,您可以使用 .A
属性。
>>> id_m.A
array([[ 1., 0., 0., 0.],
[ 0., 1., 0., 0.],
[ 0., 0., 1., 0.],
[ 0., 0., 0., 1.]])
最后一句话:
不要将您的行转换为列表! 您使用的生成器技巧的要点是尽快停止搜索。想象一下,您的每一行都有 100,000 个元素,并且每个元素都非零。生成器将查看前几个,一旦找到第一个非零值(几乎肯定在前 50 个之内),它将跳过该行的其余部分(> 99,950)。如果您转换为列表,您将放弃这种节省,因为要生成等效列表,必须读取每个元素。这也是为什么在这种情况下生成器可以与矢量化 numpy 函数竞争的原因。
您的 next
表达式有效:
In [793]: [next((i for i,x in enumerate(row) if x),None) for row in np.eye(10)]
Out[793]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
好的,这给出了第一个非零值的索引,但在我的示例中,它比 1
值更有趣。
In [801]: [row.nonzero()[0][0] for row in np.eye(10)]
Out[801]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
但是如果数组中有一行全0,比如in
arr =np.diag(np.arange(0,20,2))
nonzero
版本引发错误。它需要对 nonzero
returns 空列表的情况敏感。
要从 idx
列表中获取值,请使用
arr[np.arange(len(idx)), idx]
计时
对于大型对角线阵列,nonzero
明显更快:
In [822]: arr =np.diag(np.arange(1,2000,2))
In [823]: timeit idx = [next((i for i,x in enumerate(row) if x),None) for row in arr]
10 loops, best of 3: 87.6 ms per loop
In [824]: timeit [row.nonzero()[0][0] for row in arr]
100 loops, best of 3: 6.44 ms per loop
对于相同大小的数组,所有 1 都在行的前面,next
方法稍微快一些。
In [825]: arr = np.zeros_like(arr,int)
In [826]: arr[:,10]=1
In [827]: timeit idx = [next((i for i,x in enumerate(row) if x),None) for row in arr]
100 loops, best of 3: 3.61 ms per loop
In [828]: timeit [row.nonzero()[0][0] for row in arr]
100 loops, best of 3: 6.41 ms per loop
Python 中的短路循环与 C 代码中的完整循环之间存在权衡。
argmax
是在每行中查找第一个非零索引的另一种方法:
idx = np.argmax(arr>0, axis=1)
使用轴参数 argmax
必须按行迭代,然后在行内迭代,但它在编译代码中这样做。使用这样的布尔参数,argmax
会短路。我在另一个关于 argmax
(或最小值)和 nan
值的问题中对此进行了探讨,它们也会短路。
另一种可能(窜@Divakar
?)
def foo(arr):
I,J=np.where(arr>0)
u,i=np.unique(I,return_index=True)
return J[i]
我有一个 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]]
即使在我将行转换为列表后也会出现这种情况
有没有什么方法可以将每一行转换为一个列表,这样我就可以找到第一个非零值的索引,或者是否有另一种更简单的方法来做到这一点?
您不需要 "convert a numpy array to list",您需要更好的方法来查找 non-zero 元素。为此你应该使用 nonzero
:
Return the indices of the elements that are non-zero.
诸如此类:
import numpy as np
arr = np.array([0, 0, 9, 2])
print(arr[arr.nonzero()][0])
# 9
或者:
import numpy as np
matrix = np.array([[0, 0, 9, 2], [0, 3, 0, 1]])
for row in matrix:
print(row[row.nonzero()][0])
# 9
# 3
我的猜测是,与包括我在内的许多其他人一样,您被 np.matrix
class.
切片此 class 的实例会产生意外结果:
>> id = np.identity(4)
>>> type(id)
<class 'numpy.ndarray'>
>>> id[2]
array([ 0., 0., 1., 0.]) # shape == (4,)
>>> id_m = np.matrix(id)
>> type(id_m)
<class 'numpy.matrixlib.defmatrix.matrix'>
>>> id_m[2]
matrix([[ 0., 0., 1., 0.]]) # shape == (4, 1)
如您所料,这可能也是您的生成器技巧不起作用的原因。
迭代一行 np.matrix
会因为它一次性嵌套了 return 整行然后停止。
如果出于某种原因您正在处理一个矩阵,但希望它表现得像一个数组,您可以使用 .A
属性。
>>> id_m.A
array([[ 1., 0., 0., 0.],
[ 0., 1., 0., 0.],
[ 0., 0., 1., 0.],
[ 0., 0., 0., 1.]])
最后一句话:
不要将您的行转换为列表! 您使用的生成器技巧的要点是尽快停止搜索。想象一下,您的每一行都有 100,000 个元素,并且每个元素都非零。生成器将查看前几个,一旦找到第一个非零值(几乎肯定在前 50 个之内),它将跳过该行的其余部分(> 99,950)。如果您转换为列表,您将放弃这种节省,因为要生成等效列表,必须读取每个元素。这也是为什么在这种情况下生成器可以与矢量化 numpy 函数竞争的原因。
您的 next
表达式有效:
In [793]: [next((i for i,x in enumerate(row) if x),None) for row in np.eye(10)]
Out[793]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
好的,这给出了第一个非零值的索引,但在我的示例中,它比 1
值更有趣。
In [801]: [row.nonzero()[0][0] for row in np.eye(10)]
Out[801]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
但是如果数组中有一行全0,比如in
arr =np.diag(np.arange(0,20,2))
nonzero
版本引发错误。它需要对 nonzero
returns 空列表的情况敏感。
要从 idx
列表中获取值,请使用
arr[np.arange(len(idx)), idx]
计时
对于大型对角线阵列,nonzero
明显更快:
In [822]: arr =np.diag(np.arange(1,2000,2))
In [823]: timeit idx = [next((i for i,x in enumerate(row) if x),None) for row in arr]
10 loops, best of 3: 87.6 ms per loop
In [824]: timeit [row.nonzero()[0][0] for row in arr]
100 loops, best of 3: 6.44 ms per loop
对于相同大小的数组,所有 1 都在行的前面,next
方法稍微快一些。
In [825]: arr = np.zeros_like(arr,int)
In [826]: arr[:,10]=1
In [827]: timeit idx = [next((i for i,x in enumerate(row) if x),None) for row in arr]
100 loops, best of 3: 3.61 ms per loop
In [828]: timeit [row.nonzero()[0][0] for row in arr]
100 loops, best of 3: 6.41 ms per loop
Python 中的短路循环与 C 代码中的完整循环之间存在权衡。
argmax
是在每行中查找第一个非零索引的另一种方法:
idx = np.argmax(arr>0, axis=1)
使用轴参数 argmax
必须按行迭代,然后在行内迭代,但它在编译代码中这样做。使用这样的布尔参数,argmax
会短路。我在另一个关于 argmax
(或最小值)和 nan
值的问题中对此进行了探讨,它们也会短路。
另一种可能(窜@Divakar
?)
def foo(arr):
I,J=np.where(arr>0)
u,i=np.unique(I,return_index=True)
return J[i]