【问题标题】:What is the most efficient way to remove any matrix from a list of matrices when the matrix contains at least one nan?当矩阵包含至少一个 nan 时,从矩阵列表中删除任何矩阵的最有效方法是什么?
【发布时间】:2021-10-30 05:15:51
【问题描述】:

我有一个矩阵列表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()。删除循环中的最后一行会删除错误,但我不明白为什么,因为我只是尝试执行基本的列表操作。

还有没有更简单的方法可以在不使用循环的情况下实现我的目标?

【问题讨论】:

  • 您还没有给我们一个样本M_list 来使用。我想我们应该自己生成?如果您发布一个运行脚本,那么我们可以根据该运行脚本得出答案。
  • 对于一个包含 7 个 5×5 矩阵的列表,每个矩阵包含两个 nan,这样可以: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)
  • 这里有很多方法可以检查单个数组中的 nan stackoverflow.com/questions/6736590/fast-check-for-nan-in-numpy
  • 感谢您的代码。将其添加到问题中(连同import numpy as np),以便快速复制/粘贴给我们一个运行脚本。

标签: python numpy nan


【解决方案1】:

您可以使用isnanany

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

【讨论】:

  • 非常优雅。谢谢!
【解决方案2】:

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

制作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 循环仅在循环中未更改(添加或删除)列表时才有效。否则,您应该制作一个新列表,保持原样不变。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 2022-08-17
    • 2012-06-17
    • 2016-05-22
    • 1970-01-01
    • 2021-05-02
    • 1970-01-01
    相关资源
    最近更新 更多