用零替换python数组中的骨骼

时间:2012-12-27 20:29:39

标签: python numpy matplotlib nonetype map-function

我刚刚加入了两个不等长的数组和命令:

allorders = map(None,todayorders, lastyearorders)

其中“none”给出今天的订单没有值(因为今天的数组不长)。

但是,当我尝试将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社区),请提供从头到尾的详细代码,我可以使用/测试。

3 个答案:

答案 0 :(得分:6)

使用列表理解:

allorders = [i if i[0] is not None else (0, i[1]) for i in allorders]

答案 1 :(得分:4)

因为听起来你希望这一切都在numpy中,所以对你的问题的直接回答实际上只是一个旁边,并且正确的答案不会存在"当然......"段落。

如果您考虑一下,那么您使用map None第一个参数作为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 None,显示为较短列表的额外值;如果你想用None取代每个 0,你必须按照Martijn Pieters的方式来做。但我认为这就是你想要的。

另请注意,最后list(allorders)izip_longestitertools中的大多数内容一样,返回迭代器,而不是list。或者,就你可能更熟悉而言,它会返回一个懒惰的"顺序而不是严格的#34;一。如果你只是要迭代结果,那实际上更好,但是如果你需要使用一些需要list的函数(比如以人类可读的形式打印出来) - 或访问allorders[9],如您的示例中所示,您需要先显式转换它。

如果您确实需要numpy.array而不是list,则可以直接到达那里,而无需先通过list。 (如果你所做的只是matplotlib它,你可能想要一个array。)最明显的方法是使用{{ 1}}而不是np.fromiter(allorders)。您可能希望传递明确的list(allorders)(或任何适当的)。而且,如果您知道尺寸(您执行的操作dtype=int),在某些情况下,传递明确的max(len(todayorders), len(lastyearorders))也会更快或更简单。

当然,如果任何count内容听起来很有吸引力,那么您可能应该首先留在numpy内,而不是使用numpymap

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]]) 函数,它接受一对数组并扩展一个以匹配另一个(或者,如果你不仅仅是处理1D,在每个轴上扩展较短的一个以制作另一个。)

无论如何,除了比使用zeroextendmap等更快且使用更少的临时内存之外,这也意味着你最终得到一个右{{1 (izip_longest而不是dtype) - 这意味着你的结果也使用较少的长期记忆,从那时起你所做的一切也会更快,并且使用更少的临时记忆。

为了完整性: 可以int处理object值,但我不认为它是你想要的。例如,您可以将pyplot方法将None方法转换为Transform的{​​{1}}对象传递给它。但这与Martijn Pieters的答案实际上是一样的,但更加冗长,除非你需要绘制大量这样的阵列,否则根本就没有优势。

答案 2 :(得分:2)

numpy:

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

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

allorders[allorders == None] = 0

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

allorders.astype(int)