matplotlib中的层次结构 [英] Hierarchy in matplotlib

查看:92
本文介绍了matplotlib中的层次结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据这篇文章,matplotlib中的所有内容都组织在层次结构.层次结构的顶部是 matplotlib 状态机环境",由 matplotlib.pyplot 模块提供.在此级别,使用简单函数将绘图元素(线条、图像、文本等)添加到当前图形中的当前轴.层次结构中的下一层是面向对象界面的第一层,其中 pyplot 仅用于图形创建等少数功能,用户显式创建并跟踪图和轴对象.在这一层,用户使用 pyplot 来创建图形,通过这些图形,可以创建一个或多个轴对象.这些轴对象然后用于大多数绘图操作.还有其他术语,例如图形",轴",轴",艺术家"(在提到的页面上有一张漂亮的图片解释了所有这些内容).总结:

  1. 一切都属于 matplotlib.pyplot 模块
  2. 人物-跟踪所有子轴,散布着一些特殊"艺术家(标题,人物传说等)
  3. 轴 - 具有数据空间的图像区域 - 属于图
  4. 轴-标记刻度线(x,y,z坐标等)的字符串-属于轴
  5. 艺术家 - 您可以在图形上看到的所有内容(甚至图形、轴和轴对象)- 都属于图形

创建新图形的最简单方法是使用pyplot:

  fig = plt.figure()#没有轴的空图形fig,ax_lst = plt.subplots(2,2)#带有2x2轴网格的图形

我经常看到这两种方法可以互换使用,我希望它们基本上是等效的.但是我无法使用 fig, ax = plt.subplots() 获得相同的结果,因为我使用 fig = plt.figure()ax = fig.add_subplot(111,projection='3d')

这是我的实验,对于plt.figure():

 在[1]中:从mpl_toolkits.mplot3d导入Axes3D在[2]中:将matplotlib.pyplot导入为plt在 [3]: fig = plt.figure()在[4]中:ax = fig.add_subplot(111,projection ='3d')在[5]中:无花果输出[5]:<matplotlib.figure.Figure at 0x7f8377ca0610>在[6]中:斧头输出[6]:<matplotlib.axes._subplots.Axes3DSubplot at 0x7f8377bfb310>在 [7] 中:

这是我的实验,用于 plt.subplots():

In [1]: from mpl_toolkits.mplot3d import Axes3D在[2]中:将matplotlib.pyplot导入为plt在[3]中:图,ax = plt.subplots()在 [4]:无花果Out [4]:< matplotlib.figure.0x7f3dcf96e710处的图>在 [5] 中:斧头输出[5]:<matplotlib.axes._subplots.AxesSubplot at 0x7f3dced564d0>在 [6] 中:

您可以看到第一个创建了 matplotlib.axes._subplots.Axes3DSubplot 对象,第二个创建了 matplotlib.axes._subplots.AxesSubplot 对象.我一直在通过 help(plt.subplots) 搜索 projection 关键字,但没有找到任何东西.因此,我尝试对 plt.subplots 使用与 fig.add_subplot 相同的参数,但出现以下错误:

In [7]: fig, ax = plt.subplots(111,projection='3d')---------------------------------------------------------------------------TypeError Traceback(最近一次通话)< ipython-input-7-a905adad48f5>在< module>()中---->1 fig, ax = plt.subplots(111,projection='3d')/usr/lib/python2.7/dist-packages/matplotlib/pyplot.pyc在子图中(行,ncol,sharex,sharey,挤压,subplot_kw,gridspec_kw,** fig_kw)1076 gridspec_kw = {}1077->第1078话1079 gs = GridSpec(nrows,ncols,**gridspec_kw)1080图中的/usr/lib/python2.7/dist-packages/matplotlib/pyplot.pyc(num, figsize, dpi, facecolor, edgecolor, frameon, FigureClass, **kwargs)433 frameon = frameon,434 FigureClass = FigureClass,->第 435 章436第437章真相大白/usr/lib/python2.7/dist-packages/matplotlib/backends/backend_tkagg.pyc in new_figure_manager(num, *args, **kwargs)第78话79 FigureClass = kwargs.pop('FigureClass',图)--->80图= FigureClass(* args,** kwargs)81 返回 new_figure_manager_given_figure(num, figure)82TypeError:__init __()获得了意外的关键字参数'projection'

问题:

fig, ax = plt.subplots()fig = plt.figure();ax = fig.add_subplot(111,projection ='3d')等价物,如果是的话,如何在示例中使用 fig,ax = plt.subplots()?

在提到的页面上,还有以下代码:

#!/bin/env python导入matplotlib.pyplot作为plt将numpy导入为npx = np.linspace(0,2,100)#首次调用plt.plot会自动创建必要的图形和轴以获取所需的图.plt.plot(x, x, label='linear')# 对 plt.plot 的后续调用重新使用当前坐标轴,并每次添加另一行.plt.plot(x,x ** 2,label ='quadratic')plt.plot(x,x ** 3,label ='cubic')#设置标题,图例和轴标签也会自动使用当前轴并分别设置标题,创建图例和标记轴.plt.xlabel('x 标签')plt.ylabel('y 标签')plt.title("简单情节")plt.legend()plt.show()

如你所见,没有这样的函数 fig = plt.figure() 也没有 fig, ax_lst = plt.subplots(2, 2)

问题:

这个例子中的层次结构是如何维护的,图是默认创建的还是发生了什么?

解决方案

问题1

我认为您已经为自己证明了这些命令并不完全等效,只是希望对此有所保证.

要做你想做的事 - 你可以通过设置一个字典将 projection 传递给 add_subplot() 调用,这些调用在幕后"使用子图参数并将它们传递给例如

from mpl_toolkits.mplot3d 导入 Axes3D导入matplotlib.pyplot作为pltsubplot_args = {'projection':'3d'}图, ax = plt.subplots(subplot_kw=subplot_args)

在此处的文档中.

问题 2

图形轴等都是在 plt.plot 的第一行在封面下"创建的. pyplot 模块将保持状态并重用相同的图形实例和轴实例,直到调用 plt.show().

注意 - 就目前而言,您无法处理这些实例.如果需要,您总是可以得到帮助.通过调用

fig = plt.gcf()

  ax = plt.gca()

其中 gcf()gca() 分别是获取当前图形和获取当前轴.这是以 matplotlib 最初基于的 matlab 功能为模型的.

如果您真的很想看看自动创建的完成方式-都是开源的.您可以在此处的代码.这反过来调用gcf()寻找FigureManager(实际上是维护状态的东西).如果存在,它返回它管理的图形,否则它使用 plt.figure().同样,此过程在某种程度上继承自matlab,在该过程中,最初的调用通常是在执行任何绘图操作之前的 figure .


附录

我认为您可能会想到的是如何使用 plt.plot()之类的 matplotlib.pyplot 函数为您提供 访问权限 到文档中描述的层次结构.答案是,如果您想要真正细粒度的控制,有时不会.这就是为什么人们使用

fig, ax = plt.subplots()

样式或类似样式,以便它们可以直接控制图形和轴对象,并可以根据需要对其进行操作.

According to this article, everything in matplotlib is organized in a hierarchy. At the top of the hierarchy is the matplotlib "state-machine environment" which is provided by the matplotlib.pyplot module. At this level, simple functions are used to add plot elements (lines, images, text, etc.) to the current axes in the current figure. The next level down in the hierarchy is the first level of the object-oriented interface, in which pyplot is used only for a few functions such as figure creation, and the user explicitly creates and keeps track of the figure and axes objects. At this level, the user uses pyplot to create figures, and through those figures, one or more axes objects can be created. These axes objects are then used for most plotting actions. There are also other terms like Figure, Axes, Axis, Artist (there is nice picture which explains all of those, on mentioned page). In summary:

  1. Everything belongs to matplotlib.pyplot module
  2. Figure - keeps track of all the child Axes, a smattering of ‘special’ artists (titles, figure legends, etc)
  3. Axes - region of the image with the data space - belongs to Figure
  4. Axis - strings labeling the ticks (x,y,z coordinates etc) - belongs to Axes
  5. Artist - everything you can see on the figure (even the Figure, Axes, and Axis objects) - belongs to Figure

The easiest way to create a new figure is with pyplot:

fig = plt.figure()  # an empty figure with no axes
fig, ax_lst = plt.subplots(2, 2)  # a figure with a 2x2 grid of Axes

I've often seen those two approaches used interchangeably, and I hoped they are basically equivalents. But I cannot achieve same result using the fig, ax = plt.subplots() as I get using the fig = plt.figure() and ax = fig.add_subplot(111, projection='3d')

Here are my experiments, for plt.figure():

In [1]: from mpl_toolkits.mplot3d import Axes3D

In [2]: import matplotlib.pyplot as plt

In [3]: fig = plt.figure()

In [4]: ax = fig.add_subplot(111, projection='3d')

In [5]: fig
Out[5]: <matplotlib.figure.Figure at 0x7f8377ca0610>

In [6]: ax
Out[6]: <matplotlib.axes._subplots.Axes3DSubplot at 0x7f8377bfb310>

In [7]: 

Here are my experiments, for plt.subplots():

In [1]: from mpl_toolkits.mplot3d import Axes3D

In [2]: import matplotlib.pyplot as plt

In [3]: fig, ax = plt.subplots()

In [4]: fig
Out[4]: <matplotlib.figure.Figure at 0x7f3dcf96e710>

In [5]: ax
Out[5]: <matplotlib.axes._subplots.AxesSubplot at 0x7f3dced564d0>

In [6]: 

As you can see the first creates the matplotlib.axes._subplots.Axes3DSubplot object while the second creates matplotlib.axes._subplots.AxesSubplot object. I've been searching through help(plt.subplots) for projection keyword but I did not find anything. So I've tried to use same arguments for plt.subplots as for fig.add_subplot but I get the following error:

In [7]: fig, ax = plt.subplots(111, projection='3d')
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-7-a905adad48f5> in <module>()
----> 1 fig, ax = plt.subplots(111, projection='3d')

/usr/lib/python2.7/dist-packages/matplotlib/pyplot.pyc in subplots(nrows, ncols, sharex, sharey, squeeze, subplot_kw, gridspec_kw, **fig_kw)
   1076         gridspec_kw = {}
   1077 
-> 1078     fig = figure(**fig_kw)
   1079     gs = GridSpec(nrows, ncols, **gridspec_kw)
   1080 

/usr/lib/python2.7/dist-packages/matplotlib/pyplot.pyc in figure(num, figsize, dpi, facecolor, edgecolor, frameon, FigureClass, **kwargs)
    433                                         frameon=frameon,
    434                                         FigureClass=FigureClass,
--> 435                                         **kwargs)
    436 
    437         if figLabel:

/usr/lib/python2.7/dist-packages/matplotlib/backends/backend_tkagg.pyc in new_figure_manager(num, *args, **kwargs)
     78     """
     79     FigureClass = kwargs.pop('FigureClass', Figure)
---> 80     figure = FigureClass(*args, **kwargs)
     81     return new_figure_manager_given_figure(num, figure)
     82 

TypeError: __init__() got an unexpected keyword argument 'projection'

Question:

Are fig, ax = plt.subplots() and fig = plt.figure(); ax = fig.add_subplot(111, projection='3d') equivalents, if yes how can I use fig, ax = plt.subplots() in my example?

On the mentioned page there is also following code:

#!/bin/env python

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 2, 100)

# The first call to plt.plot will automatically create the necessary figure and axes to achieve the desired plot.
plt.plot(x, x, label='linear')

# Subsequent calls to plt.plot re-use the current axes and each add another line.
plt.plot(x, x**2, label='quadratic')
plt.plot(x, x**3, label='cubic')

# Setting the title, legend, and axis labels also automatically use the current axes and set the title, create the legend, and label the axis respectively.
plt.xlabel('x label')
plt.ylabel('y label')

plt.title("Simple Plot")

plt.legend()

plt.show()

As you can see there are no such functions fig = plt.figure() nor fig, ax_lst = plt.subplots(2, 2)

Question:

How is the hierarchy maintained in this example, is Figure created by default or what is going on?

解决方案

Question 1

I think you've shown for yourself that the commands are not wholly equivalent and just want some reassurance of this.

To do what you want to do - you can pass in projection to the add_subplot() calls that are used 'under the covers' by setting up a dictionary of subplot arguments and passing them in e.g.

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
subplot_args = {'projection':'3d'}
fig, ax = plt.subplots(subplot_kw=subplot_args)

The use of the named argument subplot_kw is described in the docs here.

Question 2

The figure axes etc are all created 'under the covers' by the first line beginning plt.plot. The pyplot module is maintaining state and reusing the same figure instance and axes instance until you call plt.show().

Note - as it stands you don't have a handle to these instances. You can always get a handle if you want e.g. by calling

fig = plt.gcf()

and

ax = plt.gca()

where gcf() and gca() are get current figure and get current axes respectively. This is modelled on the matlab functionality upon which matplotlib was originally based.

If you're really keen to see how the auto creation is done - it's all open source. You can see the call to plot() creates an Axes instance by a call to gca() in the code here. This in turn calls gcf(), which looks for a FigureManager (which is what actually maintains the state). If one exists, it returns the figure it's managing, otherwise it creates a new one using plt.figure(). Again, this process to some degree inherits from matlab, where the initial call is usually figure before any plotting operation.


Addendum

I think what you might be driving at is how use of the matplotlib.pyplot functions like plt.plot() etc give you access to the hierarchy as described by the documentation. The answer is that if you want really fine grained control, it sometimes doesn't. That's why people use the

fig, ax = plt.subplots()

pattern or similar so that they have handles to the figure and axes objects directly and can manipulate them as they like.

这篇关于matplotlib中的层次结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆