在matplotlib中使用NAN的散点图的图例

时间:2015-04-20 09:14:17

标签: python matplotlib legend scatter-plot

我在为具有NAN值的散点图创建图例时遇到问题。

from numpy import *
import matplotlib
from matplotlib.pyplot import *

figure()
subplot(111)
h = scatter([NAN], [NAN], marker="o", facecolor="r", edgecolor="r", s=3)

legend([h], ["scatter"])

savefig("out.png")

close()

上面的代码因ValueError例外而失败:

Traceback (most recent call last):
  File "legend.py", line 9, in <module>
    legend([h], ["scatter"])
  File "/usr/local/lib/python2.7/site-packages/matplotlib-1.3.1-py2.7-linux-x86_64.egg/matplotlib/pyplot.py", line 3381, in legend
    ret = gca().legend(*args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/matplotlib-1.3.1-py2.7-linux-x86_64.egg/matplotlib/axes.py", line 4778, in legend
    self.legend_ = mlegend.Legend(self, handles, labels, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/matplotlib-1.3.1-py2.7-linux-x86_64.egg/matplotlib/legend.py", line 366, in __init__
    self._init_legend_box(handles, labels)
  File "/usr/local/lib/python2.7/site-packages/matplotlib-1.3.1-py2.7-linux-x86_64.egg/matplotlib/legend.py", line 630, in _init_legend_box
    handlebox)
  File "/usr/local/lib/python2.7/site-packages/matplotlib-1.3.1-py2.7-linux-x86_64.egg/matplotlib/legend_handler.py", line 103, in __call__
    handlebox.get_transform())
  File "/usr/local/lib/python2.7/site-packages/matplotlib-1.3.1-py2.7-linux-x86_64.egg/matplotlib/legend_handler.py", line 325, in create_artists
    width, height, fontsize)
  File "/usr/local/lib/python2.7/site-packages/matplotlib-1.3.1-py2.7-linux-x86_64.egg/matplotlib/legend_handler.py", line 282, in get_sizes
    size_max = max(orig_handle.get_sizes()) * legend.markerscale ** 2
ValueError: max() arg is an empty sequence

奇怪的是,只有当我将单元素NAN列表传递给scatter()时才会引发异常。结果与预期的空列表和超过1个NAN列表一样。如果我使用numpy数组而不是列表,结果是一样的。对此有解释吗?

我正在使用matplotlib版本1.3.1

3 个答案:

答案 0 :(得分:0)

以下是解决方法:尝试使用代理艺术家绘制图例。这打破了自动进入,但至少它似乎做你需要的......

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.lines import Line2D

h = plt.scatter([np.nan], [np.nan], marker="o", facecolor="r", edgecolor="r", s=3)
proxy = [Line2D(range(1), range(1), color="white", marker='o', markerfacecolor="red")]

plt.legend(proxy, ["scatter"])
plt.show()

答案 1 :(得分:0)

好的,我找到了问题的根源。

在调用scatter时遇到两个条件时出现错误:

  1. s=(标记大小)的长度等于数据长度
  2. 没有绘制点,i。即对于每个indexx[index]y[index]为NAN或INFINITY
  3. 因此,例如,这也将失败:

    scatter([NAN, 2], [3, NAN], marker="o", s=[3, 4])
    

    问题在于axes/_axes.pyscatter函数中)的第3602行:

            x, y, s, c = cbook.delete_masked_points(x, y, s, c)
    

    xy是数据点,s - 标记大小,c - 颜色)。

    delete_masked_points文档说:

      

    查找一组参数中的所有蒙版和/或非有限点,并返回仅包含未屏蔽点的参数。

         

    (...)

         

    任何长度与第一个参数(...)不同的参数都将保持不变。

    因此,如果满足前面提到的两个条件,s将变为空数组。之后,在legend函数调用中,无法计算size_max

    解决方案就是这样做:

            s_copy = s
            x, y, s, c = cbook.delete_masked_points(x, y, s, c)
            if len(s) == 0:
                s = s_copy
    

    我将向matplotlib-users发送消息

    感谢@ 7hibault的帮助!

答案 2 :(得分:0)

即使在GitHub上引发了问题,问题似乎仍然存在。它可能不会引发错误,但图例中不会出现正确的符号。

另一个运作良好的方法是使用:

    plt.plot(x, y, c=color, marker=marker_style, linestyle='None', label=label_name)

np.nan数据点的符号现在使用“plot”而不是“scatter”显示在图例中。