无法将line2d对象绘制到matplotlib 3.5.1中的轴

发布于 2025-02-01 16:41:37 字数 2454 浏览 1 评论 0原文

我正在尝试从某些单个轴(如matplotlib.axes.axes.axes.axes对象)提取行(AS matplotlib.lines.line.line2d对象) (带有子图)。我正在尝试使用axes.add_line(),如上所述在这里函数以实现此目的,如下所示:

import matplotlib.pyplot as plt
from matplotlib.figure import Figure

figS = Figure(figsize=(15, 5))
figC = Figure(figsize=(15, 5))
figT = Figure(figsize=(15, 5))
yS = np.sin(t)
yC = np.cos(t)
yT = np.tan(t)
axS = figS.add_axes([0, 0, 1, 1])
lS = axS.plot(t, yS)
axC = figC.add_axes([0, 0, 1, 1])
lC = axC.plot(t, yC)
axT = figT.add_axes([0, 0, 1, 1])
lT = axT.plot(t, yT)


supSFig, axsSF = plt.subplots(3, figsize=(15, 15))
axsSF[0].add_line(lS)
axsSF[1].add_line(lC)
axsSF[2].add_line(lT)

但是我会收到以下警告/错误:

MatplotlibDeprecationWarning: Passing argument *line* of unexpected type list to add_line which only accepts <class 'matplotlib.lines.Line2D'> is deprecated since 3.5 and will become an error two minor releases later.
AttributeError                            Traceback (most recent call last)
Input In [79], in <cell line: 2>()
      1 supSFig, axsSF = plt.subplots(3, figsize=(15, 15))
----> 2 axsSF[0].add_line(lS)
      3 axsSF[1].add_line(lC)
      4 axsSF[2].add_line(lT)

File /usr/local/lib/python3.8/dist-packages/matplotlib/axes/_base.py:2279, in _AxesBase.add_line(self, line)
   2275 """
   2276 Add a `.Line2D` to the Axes; return the line.
   2277 """
   2278 self._deprecate_noninstance('add_line', mlines.Line2D, line=line)
-> 2279 self._set_artist_props(line)
   2280 if line.get_clip_path() is None:
   2281     line.set_clip_path(self.patch)

File /usr/local/lib/python3.8/dist-packages/matplotlib/axes/_base.py:1101, in _AxesBase._set_artist_props(self, a)
   1099 def _set_artist_props(self, a):
   1100     """Set the boilerplate props for artists added to Axes."""
-> 1101     a.set_figure(self.figure)
   1102     if not a.is_transform_set():
   1103         a.set_transform(self.transData)

AttributeError: 'list' object has no attribute 'set_figure'

我从我引用 在较早的版本中可能是可能的,现在是折衷的功能。我正在使用matplotlib版本3.5.1。 我现在如何实现相同的功能?是否有解决方法或任何较新的功能将线对象绘制到Axes对象中?

I'm trying to extract lines (as matplotlib.lines.Line2D objects) from some individual axes (as matplotlib.axes.Axes object) and plot it on a different plot (with say subplots). I'm trying to use Axes.add_line() as mentioned here function to achieve this as shown below:

import matplotlib.pyplot as plt
from matplotlib.figure import Figure

figS = Figure(figsize=(15, 5))
figC = Figure(figsize=(15, 5))
figT = Figure(figsize=(15, 5))
yS = np.sin(t)
yC = np.cos(t)
yT = np.tan(t)
axS = figS.add_axes([0, 0, 1, 1])
lS = axS.plot(t, yS)
axC = figC.add_axes([0, 0, 1, 1])
lC = axC.plot(t, yC)
axT = figT.add_axes([0, 0, 1, 1])
lT = axT.plot(t, yT)


supSFig, axsSF = plt.subplots(3, figsize=(15, 15))
axsSF[0].add_line(lS)
axsSF[1].add_line(lC)
axsSF[2].add_line(lT)

But I get the following Warning/Error:

MatplotlibDeprecationWarning: Passing argument *line* of unexpected type list to add_line which only accepts <class 'matplotlib.lines.Line2D'> is deprecated since 3.5 and will become an error two minor releases later.
AttributeError                            Traceback (most recent call last)
Input In [79], in <cell line: 2>()
      1 supSFig, axsSF = plt.subplots(3, figsize=(15, 15))
----> 2 axsSF[0].add_line(lS)
      3 axsSF[1].add_line(lC)
      4 axsSF[2].add_line(lT)

File /usr/local/lib/python3.8/dist-packages/matplotlib/axes/_base.py:2279, in _AxesBase.add_line(self, line)
   2275 """
   2276 Add a `.Line2D` to the Axes; return the line.
   2277 """
   2278 self._deprecate_noninstance('add_line', mlines.Line2D, line=line)
-> 2279 self._set_artist_props(line)
   2280 if line.get_clip_path() is None:
   2281     line.set_clip_path(self.patch)

File /usr/local/lib/python3.8/dist-packages/matplotlib/axes/_base.py:1101, in _AxesBase._set_artist_props(self, a)
   1099 def _set_artist_props(self, a):
   1100     """Set the boilerplate props for artists added to Axes."""
-> 1101     a.set_figure(self.figure)
   1102     if not a.is_transform_set():
   1103         a.set_transform(self.transData)

AttributeError: 'list' object has no attribute 'set_figure'

I understand from the date mentioned in the post which I referred that it was possible in earlier versions and is a deprecated feature now. I'm using matplotlib version 3.5.1.
How do I achieve the same functionality now? Is there a workaround or any newer feature to plot line object into axes object?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

〗斷ホ乔殘χμё〖 2025-02-08 16:41:37

After a bit of reading, I happened to come across

覆盖基本方法,因此艺术家可以包含另一个艺术家。

因此,添加以下内容将有所帮助:

import matplotlib.lines as lines
import matplotlib.transforms as mtransforms
import matplotlib.text as mtext

class CustLine(lines.Line2D):
    def __init__(self, *args, **kwargs):
        # we'll update the position when the line data is set
        self.text = mtext.Text(0, 0, '')
        super().__init__(*args, **kwargs)

        # we can't access the label attr until *after* the line is
        # initiated
        self.text.set_text(self.get_label())

    def set_figure(self, figure):
        self.text.set_figure(figure)
        super().set_figure(figure)

    def set_axes(self, axes):
        self.text.set_axes(axes)
        super().set_axes(axes)

    def set_transform(self, transform):
        # 2 pixel offset
        texttrans = transform + mtransforms.Affine2D().translate(2, 2)
        self.text.set_transform(texttrans)
        super().set_transform(transform)

    def set_data(self, x, y):
        if len(x):
            self.text.set_position((x[-1], y[-1]))

        super().set_data(x, y)

    def draw(self, renderer):
        # draw my label at the end of the line with 2 pixel offset
        super().draw(renderer)
        self.text.draw(renderer)

现在,需要完成的所有操作是替换以下内容:

supSFig, axsSF = plt.subplots(3, figsize=(15, 15))
axsSF[0].add_line(lS)
axsSF[1].add_line(lC)
axsSF[2].add_line(lT)

使用:

supSFig, axsSF = plt.subplots(3, figsize=(15, 15))
axsSF[0].add_line(CustLine(lS[0].get_xdata(), lS[0].get_ydata()))
axsSF[1].add_line(CustLine(lC[0].get_xdata(), lC[0].get_ydata()))
axsSF[2].add_line(CustLine(lT[0].get_xdata(), lT[0].get_ydata()))

这是很好的作用,似乎是将行传递到axes.add_lines()方法的最佳方法matplotlib v3.5+。也欢迎其他任何解决方法。

ps:请注意,xdataydata是强制性参数。

After a bit of reading, I happened to come across this doc. As mentioned in the title Artist within an artist, the above error basically is the result of a restriction somewhere. The error is not an obvious one, so according to the example, we need to:

Override basic methods so an artist can contain another artist.

Hence, adding the following would help:

import matplotlib.lines as lines
import matplotlib.transforms as mtransforms
import matplotlib.text as mtext

class CustLine(lines.Line2D):
    def __init__(self, *args, **kwargs):
        # we'll update the position when the line data is set
        self.text = mtext.Text(0, 0, '')
        super().__init__(*args, **kwargs)

        # we can't access the label attr until *after* the line is
        # initiated
        self.text.set_text(self.get_label())

    def set_figure(self, figure):
        self.text.set_figure(figure)
        super().set_figure(figure)

    def set_axes(self, axes):
        self.text.set_axes(axes)
        super().set_axes(axes)

    def set_transform(self, transform):
        # 2 pixel offset
        texttrans = transform + mtransforms.Affine2D().translate(2, 2)
        self.text.set_transform(texttrans)
        super().set_transform(transform)

    def set_data(self, x, y):
        if len(x):
            self.text.set_position((x[-1], y[-1]))

        super().set_data(x, y)

    def draw(self, renderer):
        # draw my label at the end of the line with 2 pixel offset
        super().draw(renderer)
        self.text.draw(renderer)

Now, all that needs to be done is replace the following:

supSFig, axsSF = plt.subplots(3, figsize=(15, 15))
axsSF[0].add_line(lS)
axsSF[1].add_line(lC)
axsSF[2].add_line(lT)

with:

supSFig, axsSF = plt.subplots(3, figsize=(15, 15))
axsSF[0].add_line(CustLine(lS[0].get_xdata(), lS[0].get_ydata()))
axsSF[1].add_line(CustLine(lC[0].get_xdata(), lC[0].get_ydata()))
axsSF[2].add_line(CustLine(lT[0].get_xdata(), lT[0].get_ydata()))

This works well and seems like the best way to pass lines to Axes.add_lines() method for matplotlib v3.5+. Any other workarounds are welcome too.

P.S.: Please note that xdata and ydata are mandatory arguments.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文