2

我刚刚将两个长度不等的数组与命令一起加入:

allorders = map(None,todayorders, lastyearorders)

在今天的订单没有值的地方给出“无”(因为今天的订单数组没有那么长)。

但是,当我尝试将 allorders 数组传递到 matplotlib 条形图中时:

 p10= plt.bar(ind, allorders[9],   width, color='#0000DD', bottom=allorders[8])

..我收到以下错误:

TypeError: unsupported operand type(s) for +=: 'int' and 'NoneType'

那么,matplotlib 有没有办法不接受任何数据类型?如果没有,如何在我的 allorders 数组中用零替换“Nones”?

如果可以,因为我是 Python 新手(来自 R 社区),请提供从头到尾的详细代码,我可以使用/测试。

4

3 回答 3

8

使用列表推导:

allorders = [i if i[0] is not None else (0, i[1]) for i in allorders]
于 2012-12-27T20:30:36.117 回答
5

使用 numpy:

import numpy as np
allorders = np.array(allorders)

由于 Nones,这会创建一个对象数组。我们可以用零替换它们:

allorders[allorders == None] = 0

然后将数组转换为正确的类型:

allorders.astype(int)
于 2017-11-01T19:29:32.067 回答
4

由于听起来您希望这一切都在numpy,因此您的问题的直接答案实际上只是一个旁白,而正确的答案直到“当然……”段落才出现。

如果您考虑一下,您将使用mapNone一个参数作为 a 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的s;None如果你想用 a替换every ,你必须按照 Martijn Pieters 的方式来做。但我认为这就是你想要的。None0

另外,请注意,list(allorders)最后:与 中的izip_longest大多数东西一样itertools,返回一个迭代器,而不是一个list. 或者,用您可能更熟悉的术语来说,它返回一个“惰性”序列而不是“严格”序列。如果您只是要迭代结果,那实际上会更好,但是如果您需要将它与需要 a 的某些功能一起使用list(例如以人类可读的形式打印出来 - 或访问allorders[9],如您的示例中所示),您需要先显式转换它。

如果您实际上想要 anumpy.array而不是 a list,则可以直接到达那里,而无需先经过 a list。(如果你要做的只是matplotlib它,你可能确实想要一个array。)最清楚的方法是只使用np.fromiter(allorders)而不是list(allorders). 您可能想要传递一个明确的dtype=int(或任何适当的)。而且,如果您知道大小(您知道它是max(len(todayorders), len(lastyearorders))),在某些情况下,传递显式count也更快或更简单。

当然,如果任何numpy东西听起来很吸引人,你可能应该首先留在里面numpy,而不是使用mapor izip_longest

>>> todayorders.resize(lastyearorders.shape)
>>> allorders = np.vstack(todayorders, lastyearorders).transpose()

不幸的是, mutates 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函数,它接受一对数组并扩展一个以匹配另一个(或者,如果你不只是处理一维,将每个轴上较短的一个扩展到做另一个)。

无论如何,除了比使用map,izip_longest等更快和使用更少的临时内存之外,这还意味着您最终会得到一个正确的数组dtypeint而不是object)——这意味着您的结果也使用更少的长期内存,从那时起你所做的一切也将更快,使用更少的临时内存。

为了完整性:可以pyplot处理None值,但我认为这不是您想要的。例如,您可以将其方法转换为的Transform对象传递给它。但这实际上与 Martijn Pieters 的答案相同,但更加冗长,除非您需要绘制大量此类数组,否则根本没有优势。transformNone0

于 2012-12-27T20:47:04.793 回答