由于您希望所有内容都在numpy
中,所以对于您的问题的直接答案只是一个旁白,而正确的答案要到“当然…”段落才开始。
如果您考虑一下,您正在使用一个第一个参数为None
的map
作为zip_longest
,因为Python没有zip_longest
。但是它确实有一个,在itertools
中 - 它允许您指定自定义的fillvalue
。因此,您可以使用izip_longest
一步完成所有操作:
>>> import itertools
>>> todayorders = [1, 2]
>>> lastyearorders = [1, 2, 3]
>>> allorders = itertools.izip_longest(todayorders, lastyearorders, fillvalue=0)
>>> list(allorders)
[(1, 1), (2, 2), (0, 3)]
这只是为较短的列表中多余的值填充了0,如果你想用0替换每一个None,你需要像Martijn Pieters那样做。但是我认为这就是你想要的。
另外,请注意末尾的list(allorders):izip_longest和itertools中的大多数内容一样,返回的是迭代器而不是列表。或者换句话说,它返回的是“惰性”序列而不是“严格”的序列。如果你只是要遍历结果,那实际上这更好,但如果你需要将其与某些需要列表(如以人类可读形式打印出来或访问allorders[9])的函数一起使用,你需要先显式地进行转换。
如果你实际上想要一个numpy.array而不是一个列表,你可以直接得到它,而不是先经过列表。 (如果你将它与matplotlib一起使用,你可能确实需要一个array。)最清晰的方法是使用np.fromiter(allorders)而不是list(allorders)。你可能需要传递一个明确的dtype=int(或适当的类型)。并且,如果你知道大小(你知道它是max(len(todayorders), len(lastyearorders))),在某些情况下,传递一个明确的count也更快或更简单。
当然,如果你觉得任何numpy的东西听起来有吸引力,你可能应该一开始就留在numpy中,而不是使用map或izip_longest:
>>> todayorders.resize(lastyearorders.shape)
>>> allorders = np.vstack(todayorders, lastyearorders).transpose()
不幸的是,这会改变todayorders
的值,据我所知,相应的不可变函数numpy.resize
没有提供零填充的方法,而是重复值。希望我错了,有人会建议更简单的方法,但如果没有,你必须明确地执行以下操作:
>>> extrazeros = np.zeros(len(lastyearorders) - len(todayorders), dtype=int)
>>> allorders = np.vstack(np.concatenate((todayorders, extrazeros)), lastyearorders)
>>> allorders = allorders.transpose()
array([[ 1, 1],
[ 2, 2],
[ 0, 3]])
当然,如果你做很多这样的事情,我会编写一个
zeroextend
函数,它接受一对数组并将其中一个扩展为与另一个匹配(或者,如果你不仅处理1D,则在每个轴上扩展较短的一个来匹配另一个)。
无论如何,除了比使用
map
、
izip_longest
等更快且使用更少的临时内存之外,这还意味着你最终得到的数组具有正确的
dtype
(而不是
object
),这意味着你的结果也使用更少的长期内存,并且从那时起你所做的所有操作都将更快并使用更少的临时内存。
为了完整起见:确实有可能让
pyplot
处理
None
值,但我认为这不是你想要的。例如,你可以传递一个转换对象给它,其
transform
方法将
None
转换为
0
。但这实际上与 Martijn Pieters 的答案相同,只是冗余度更高,除非你需要绘制大量这样的数组,否则没有任何优势。
None
替换为零,还是只替换因为长度不够而添加到todayorders
末尾的那些? - abarnertmap
(或zip
或izip_longest
或任何其他处理list
和/或一般可迭代对象的非numpy
函数)与numpy.array
对象一起使用。 - abarnert