我有一个Markov转换表的输出,这是一个包含59个浮点数的59个列表的列表。我想反转每个非0浮点数,然后对输出进行标准化,以便我再次得到一个概率列表,其中加起来为1.
我已经阅读了关于列表理解的教科书,这似乎是相关的,但我不能理解如何实现它。
列表列表为m
for i in range(59):
[1/item for item in m[i] if item > 0.]
i += 1
这会运行,但它不会改变m
。我在这段代码中使用item
是错误的吗?我应该使用其他参考吗?
答案 0 :(得分: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. ]])
答案 1 :(得分: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从列表推导的末尾(基本上过滤哪些项目处理)移到前面(因此值本身是{{ 3}}评估为1/item
或item
,具体取决于item
的值。
for i, x in enumerate(m):
m[i] = [1./item if item != 0. else item for item in x]
答案 2 :(得分:5)
[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)测试项目的快捷方式
答案 3 :(得分: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. ]]