Python:将列表中的负值设为0
这看起来应该很简单,但我在把列表中的负数设置为0时遇到了问题。以下是我的代码:
def subtract_lists(list1, list2):
list3 = list()
for i in range(0,len(list1)):
list3.append(list1[i]-list2[i])
if i < 0:
i = 0
else:
i = i
return list3
我在使用matplotlib制作堆叠条形图时用到了这个函数。基本上,list2中的一些值比list1中的值要大。对于我手头的数据,出现负值是没有意义的。实际上,任何负值在图上都会显示为一根实心的条。
补充说明:我想说一下,图表的顶部是list3。
补充说明2:感谢大家的帮助。由于简单,我最终使用了这个:
def subtract_lists(list1, list2):
list3 = list()
for i in range(0,len(list1)):
list3.append(max(list1[i]-list2[i], 0))
return list3
不过我很感激所有的解决方案和帮助,我会尝试其他一些例子,作为学习的体验。
3 个回答
你把 i
设置成了零,而不是 list3[i]
里面的内容。
if list3[i] < 0:
list3[i] = 0
你的 else
代码块里把 i=i
这样写,其实没什么用。你还缺少了一层缩进,正确的缩进应该是这样的:
def subtract_lists(list1, list2):
list3 = list()
for i in range(0,len(list1)):
list3.append(list1[i]-list2[i])
if list3[i] < 0:
list3[i] = 0
return list3
不过,我觉得把这个函数写成这样会更清晰:
def subtract_lists(list1, list2):
list3 = []
for a,b in zip(list1, list2):
diff = a - b
list3.append(diff if diff > 0 else 0)
return list3
当然,还有更简洁的解决方案(可以看看 DrV 的回答)。
一种方法是把列表转换成一个 numpy
的 array
。这样进行减法运算就简单明了了,而且你还可以用 numpy.clip
把负值变成0。此外,numpy
的运算速度也快得多(如果你在意速度的话,不过在这种情况下似乎不太需要担心)。
import numpy as np
ar1 = np.array(list1)
ar2 = np.array(list2)
ar3 = np.clip(ar1 - ar2, 0, None)
如果你不想使用 numpy
,那么只需把这一行
list3.append(list1[i] - list2[i])
改成这样
list3.append(max(list1[i] - list2[i], 0))
最后,当你在遍历列表以创建新列表时,使用列表推导式会更符合 Python 的风格:
list3 = [max(item1 - item2, 0) for item1, item2 in zip(list1, list2)]
当然,如果列表的大小适中,你还需要考虑 zip
实际上会复制列表这一点。所以如果使用 zip
时内存占用太大,你可以使用来自 itertools
模块的 izip
。在这种情况下,它可以直接替代 zip
:
from itertools import izip
list3 = [max(item1 - item2, 0) for item1, item2 in izip(list1, list2)]
list3 = []
for i in range(len(list1)):
list3.append(max(list1[i] - list2[i], 0))
或者
list3 = [ max(li1-li2, 0) for li1, li2 in zip(list1, list2) ]
zip
这个功能可以让你同时遍历两个列表,也就是说你可以同时拿到两个列表中相同位置的元素。个人认为这是用Python处理这个问题最优雅的方法,而且在处理两个列表时,这种方式可能也是最快的。max
函数可以处理负数的情况,因为在这种情况下,零会比li1-li2
大,然后被放入list3
中。
jsw
提供的解决方案也不错,但把列表转换成ndarray
(NumPy数组)的过程比较慢。而且,遗憾的是,NumPy并不是Python标准库的一部分。