在一个列表的列表中反转浮点数

5
我有一份马尔可夫转移表的输出,其中包含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。我不太确定那是什么意思。你是说我需要改变列表中的值吗?你能给我演示一下怎么做吗? - Richard Hames
啊,谢谢你提供的额外信息。 - Richard Hames
1
虽然这个计算本身并没有表明需要使用什么,但我建议你在数值分析中使用numpy数组而不是Python列表:原因在这里 - jpp
这是我今天早些时候回答过的一个问题的(不完全相同,但足够相似的)副本。 - cs95
4个回答

8

[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.        ]])

5

[item for sublist in m for item in sublist if item > 0.]

单独一行的[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 是测试 item 是否等于 0 的快捷方式)


我会选择这个解决方案,但是你不是跳过了小于等于0的项目吗?[[1./item if item > 0. else item for item in sm] for sm in m]能否改进这个解决方案? - Gsk

5

在循环中需要将其重新赋值给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 语句从列表推导式的末尾移动到开头(这基本上是过滤要处理的项目),所以该值本身是一个三元表达式,根据 item 的值评估为 1/itemitem)。

此时,您可能应该观看演示文稿 Loop like a Native 并将其重写为以下示例:

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

非常感谢。我现在有一个列表的列表,但它们的长度不同。如果项目=0,是否可以以相同的位置返回0值?就我所看到的,那个“if”后面没有可能再有“else”。 - Richard Hames
@RichardHames 这是有的。我还将 > 0 改为 != 0,以允许负值。 - Graipher
1
我的错。显然今天我阅读能力不佳,应该停止回答问题。由于类似的原因,我刚刚不得不完全重写一个关于XML问题的答案。已删除。 - holdenweb

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.        ]]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接