当矩阵至少包含一个 nan 时,从矩阵列表中删除任何矩阵的最有效方法是什么?

What is the most efficient way to remove any matrix from a list of matrices when the matrix contains at least one nan?

我有一个矩阵列表,M_list,我想有效地从列表中删除任何包含 nan

的矩阵

我的方法是查看每个矩阵,对其条目求和,如果总和为 nan:

,则从列表中删除该矩阵
import numpy as np
# generate list of seven, 5-by-5 matrices each of which 
contains two nans:

M_list=[]
for t in range(7):
    M=np.random.rand(5,5)
    M.ravel()[np.random.choice(M.size, 2, replace=False)] = 
    np.nan
    M_list.append(M)

# Now my attempt
for t in range(len(M_list)):
    array_sum = np.sum(M_list[t])
    if np.isnan(array_sum):
        M_list.remove(M_list[t])

我收到的错误消息指出,具有多个元素的数组的真值不明确。使用 a.any() 或 a.all()。删除循环中的最后一行可以消除错误,但我不明白为什么,因为我只是在尝试执行基本的列表操作。

还有没有更简单的方法来实现我的目标而不使用循环?

您可以使用 isnanany:

>>> filtered = [arr for arr in M_list if not np.isnan(arr).any()]

虽然列表理解是最好的方法,但您应该尝试理解您的尝试有什么问题。

制作M_list:

In [733]: len(M_list)
Out[733]: 7

我们可以删除第一个列表元素:

In [734]: M_list.remove(M_list[0])
In [735]: len(M_list)
Out[735]: 6

但是如果我们尝试从剩余列表中删除第二个:

In [736]: M_list.remove(M_list[1])
Traceback (most recent call last):
  File "<ipython-input-736-49c29fd4cfcc>", line 1, in <module>
    M_list.remove(M_list[1])
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

这种歧义错误经常出现在 SO 上。这是尝试在只接受标量布尔值的 Python 上下文中使用布尔数组的结果,一个简单的 True/False.

remove 必须找到“匹配”value 的列表元素。显然它遍历列表直到找到匹配项。在其他 SO 中已经指出,它首先测试 ID 是否相同。如果失败,它会测试某种值是否相等 (==)。

这就是删除 M_list[0] 有效的原因,id 匹配。但是要删除 M_list[1] 它必须首先针对列表的第一个元素进行测试,从而导致歧义错误。如果我们尝试删除 copy(),我们会得到同样的歧义错误,因为 ID 测试不再有效。

In [742]: M_list.remove(M_list[0].copy())
Traceback (most recent call last):
  File "<ipython-input-742-6d529bc24c83>", line 1, in <module>
    M_list.remove(M_list[0].copy())
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

但是您的迭代删除还有另一个问题:

for t in range(len(M_list)):
    array_sum = np.sum(M_list[t])
    if np.isnan(array_sum):
        M_list.remove(M_list[t])

M_list.remove() 从列表中删除一个项目;该列表更短,因此 M_list[t] 不再指向原始列表的 t 元素。像这样的迭代删除只有在从末尾开始迭代时才有效。通常,列表上的 for 循环仅在列表未在循环中更改(添加或删除)时才有效。否则你应该制作一个新的列表,保持原来的不变。