【问题标题】:Inverting floats in a list of lists [duplicate]在列表列表中反转浮点数[重复]
【发布时间】:2018-08-24 02:34:43
【问题描述】:

我有一个马尔可夫转换表的输出,它是一个包含 59 个列表的列表,每个列表有 59 个浮点数。我想反转每个非 0 浮点数,然后对输出进行归一化,这样我又得到了一个加起来为 1 的概率列表。

我已经阅读了关于列表推导的教科书,这似乎很相关,但我终生无法理解如何实现它。

列表列表为m

for i in range(59):
    [1/item for item in m[i] if item > 0.]
    i += 1

这会运行,但不会改变m。在这段代码中使用item 我错了吗?我应该使用其他参考吗?

【问题讨论】:

  • 感谢 Graipher。我不完全确定这意味着什么。您的意思是我需要更改列表中的值吗?你能告诉我怎么做吗?
  • 啊,感谢您提供的额外信息。
  • 虽然这个计算本身并不能证明有必要,但我建议您使用 numpy 数组而不是 Python 列表进行数值分析:here's why
  • 这是我今天早些时候回答的问题的(不准确,但足够相似)副本。

标签: python numpy nested-lists


【解决方案1】:

[1/item for item in m[i] if item > 0.] 单独在一行上会创建一个一次性对象。不是很实用。

我的建议:使用双重理解重建您的列表列表:

m = [[1./item for item in sm if item > 0.] for sm in m]

这个解决方案在浮点除法方面符合 Python 2/3,无论列表包含什么(整数或浮点数)

编辑:引用问题:“我想反转每个非 0 浮点数”,公式不正确,因为它不包含零。所以更准确的版本不是过滤,而是用三元测试表达式,使其保持为零。

m = [[1./item if item else 0. for item in sm] for sm in m]

if item 是针对 0 测试项目的快捷方式)

【讨论】:

  • 我会采用这个解决方案,但你不是跳过项目<= 0. 吗? [[1./item if item > 0. else item for item in sm] for sm in m] 可以改进解决方案吗?
【解决方案2】:

如果可能,我建议您使用专门为此目的设计的工具。

在下面的矢量化解决方案中,通过numpy就地发生反转,sklearn.preprocessing.normalize 用于归一化。

import numpy as np
from sklearn.preprocessing import normalize

arr = np.array([1, 2, 0, 1, 1, 0, 4, 0], dtype=float)

def inv(A):
    m = (A != 0)
    A[m] = 1/A[m]
    return A

res = normalize(inv(arr))

# [[ 0.54944226  0.27472113  0.          0.54944226  0.54944226  0.
#    0.13736056  0.        ]]

【讨论】:

    【解决方案3】:

    您需要在循环中将其分配回m[i]

    for i in range(len(m)):
        m[i] = [1./item if item != 0. else item for item in m[i]]
    

    并且不需要i+=1,因为for 循环会为您完成。

    为了避免子列表比原始子列表短,您需要将 if 从列表理解的末尾(基本上过滤哪些项目被处理)移到前面(因此值本身是 @987654321 @ 计算结果为 1/itemitem,具体取决于 item 的值。

    此时您可能应该观看演示文稿Loop like a Native 并将其改写为:

    for i, x in enumerate(m):
        m[i] = [1./item if item != 0. else item for item in x]
    

    【讨论】:

    • 非常感谢。我现在有一个列表列表,但它们的长度不同。如果 item = 0,有没有办法在同一个地方返回 0 值?据我所知,在“如果”之后没有“其他”可能。
    • @RichardHames 有。我还将> 0 更改为!= 0 以允许负值。
    • 我的错。显然我今天的阅读很糟糕,应该停止回答问题。出于类似的原因,我只需要完全重写一个 XML 问题的答案。已删除。
    【解决方案4】:

    [1/item for item in m[i] if item > 0.] 创建一个新列表。然后你对那个列表什么也不做。 Graipher 告诉您的是,您需要对新创建的列表的引用:
    m[i] = <your list comprehension> 将分配回列表中的行 i

    此外,请考虑使用 numpy 进行元素操作。演示:

    >>> import numpy as np
    >>> m = np.array([[1,2], [3, 0]])
    >>> m = 1.0/m
    >>> m
    array([[ 1.        ,  0.5       ],
           [ 0.33333333,         inf]])
    >>> m[m == np.inf] = 0
    >>> m
    array([[ 1.        ,  0.5       ],
           [ 0.33333333,  0.        ]])
    

    【讨论】:

      猜你喜欢
      • 2021-05-02
      • 2021-09-06
      • 1970-01-01
      • 1970-01-01
      • 2020-02-14
      • 2019-09-23
      • 2022-08-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多