passing x- and y-data as keyword arguments in matp

2019-04-08 19:52发布

问题:

Or, why doesn't

import numpy
import matplotlib.pyplot as plt
plt.plot(xdata = numpy.array([1]), ydata = numpy.array(1), color = 'red', marker = 'o')

work? c.f.

> In [21]: import numpy

> In [22]: import matplotlib.pyplot as plt

> In [23]: plt.plot(xdata = numpy.array([1]), ydata = numpy.array(1), color = 'red', marker = 'o')
> Out[23]: []

> In [24]: plt.plot([1],[1], color = 'red', marker = 'o')
> Out[24]: [<matplotlib.lines.Line2D at 0x108036890>]

> In [25]: plt.plot(1, 1, color = 'red', marker = 'o')
> Out[25]: [<matplotlib.lines.Line2D at 0x1041024d0>]

回答1:

Just to expand on what @Yann already said:

To understand why this happens, you need to understand a bit more about matplotlib's structure. To allow "matlab-isms" like plt.setp, and to maintain compatibility with older versions of python, matplotlib avoid properties and relies heavily on getters and setters. (plot is actually one of the most complex cases, simply due to all of the crazy forms of calling it supports.)

You can make a good argument that this is an outdated, unpythonic design, but that's beside the point.

What actually happens (for the simplest case of plot(x, y, other=stuff)) when you call plot is that a new matplotlib.line.Line2D object is created from the first two arguments, and then matplotlib.line.Line2D.update(kwargs) is called.

update basically does:

for key, value in kwargs.iteritems():
    func = getattr(self, 'set_'+key)
    func(value)

I'm over-simplifying, but that's the basic idea.

Also the accepted keyword argument list is basically auto-generated from anything that has a set_*. Because Line2D has set_xdata and set_ydata methods, they show up in the keyword argument list.

The point is, that the keyword arguments are never actually used until after most of the initialization of Line2D, and if you don't specify any arguments, plot won't initialize any Line2D's.

You could consider this a bug, but I doubt it would be fixed. I don't think xdata and ydata were ever intended to be used as keyword arguments.

set_xdata and set_ydata are there to allow you to quickly update a Line2D instance instead of creating a new one (For animations, etc...). They just happen to be allowed as keyword arguments due to the way matplotlib is set up.



回答2:

Why? Who knows, but it appears a line is not created unless you define x and y arguments. xdata and ydata change the data of the line only if it is created, and it seems it is not created without the parameters. Try this:

plt.plot([0],[0],xdata = [1,2,3,4], #numpy.array([3,4]),
               ydata = [4,5,6,7], #numpy.array([3,4]), 
               color = 'red', 
               marker = 'o')

It works as I think you intend it to.