首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何删除Matplotlib图中的线条

如何删除Matplotlib图中的线条
EN

Stack Overflow用户
提问于 2011-02-13 09:19:12
回答 6查看 138.2K关注 0票数 93

如何删除matplotlib轴的一行(或多行),因为它实际上被垃圾回收并释放回内存?下面的代码似乎删除了该行,但从未释放内存(即使显式调用gc.collect())

代码语言:javascript
复制
from matplotlib import pyplot
import numpy
a = numpy.arange(int(1e7))
# large so you can easily see the memory footprint on the system monitor.
fig = pyplot.Figure()
ax  = pyplot.add_subplot(1, 1, 1)
lines = ax.plot(a) # this uses up an additional 230 Mb of memory.
# can I get the memory back?
l = lines[0]
l.remove()
del l
del lines
# not releasing memory
ax.cla() # this does release the memory, but also wipes out all other lines.

那么,有没有一种方法可以从一个轴上删除一行,然后重新获得内存呢?This potential solution也不起作用。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2011-02-13 09:47:12

我要展示的是lines.pop(0) l.remove()del l的组合可以达到这个效果。

代码语言:javascript
复制
from matplotlib import pyplot
import numpy, weakref
a = numpy.arange(int(1e3))
fig = pyplot.Figure()
ax  = fig.add_subplot(1, 1, 1)
lines = ax.plot(a)

l = lines.pop(0)
wl = weakref.ref(l)  # create a weak reference to see if references still exist
#                      to this object
print wl  # not dead
l.remove()
print wl  # not dead
del l
print wl  # dead  (remove either of the steps above and this is still live)

我检查了你的大型数据集,内存的释放也在系统监视器上得到了确认。

当然,更简单的方法(当不是故障排除时)是从列表中弹出它,并在line对象上调用remove,而不创建对它的硬引用:

代码语言:javascript
复制
lines.pop(0).remove()
票数 74
EN

Stack Overflow用户

发布于 2012-11-27 08:24:46

这是我为我的一位同事打出来的一个很长的解释。我认为它在这里也会有帮助。不过,要有耐心。最后,我谈到了您遇到的真正问题。作为一个预告片,这是一个对Line2D对象的额外引用的问题。

警告:在我们开始之前,还有一个注意事项。如果你使用IPython来测试这一点,IPython会保留它自己的引用,并且并不是所有的引用都是弱引用。因此,在IPython中测试垃圾收集是不起作用的。这只会把事情搞乱。

好了,我们开始吧。每个matplotlib对象(FigureAxes等)通过各种属性提供对其子artists的访问。下面的例子很长,但应该很有启发性。

我们首先创建一个Figure对象,然后在该图中添加一个Axes对象。注意,axfig.axes[0]是相同的对象(相同的id())。

代码语言:javascript
复制
>>> #Create a figure
>>> fig = plt.figure()
>>> fig.axes
[]

>>> #Add an axes object
>>> ax = fig.add_subplot(1,1,1)

>>> #The object in ax is the same as the object in fig.axes[0], which is 
>>> #   a list of axes objects attached to fig 
>>> print ax
Axes(0.125,0.1;0.775x0.8)
>>> print fig.axes[0]
Axes(0.125,0.1;0.775x0.8)  #Same as "print ax"
>>> id(ax), id(fig.axes[0])
(212603664, 212603664) #Same ids => same objects

这也扩展到axes对象中的线:

代码语言:javascript
复制
>>> #Add a line to ax
>>> lines = ax.plot(np.arange(1000))

>>> #Lines and ax.lines contain the same line2D instances 
>>> print lines
[<matplotlib.lines.Line2D object at 0xce84bd0>]
>>> print ax.lines
[<matplotlib.lines.Line2D object at 0xce84bd0>]

>>> print lines[0]
Line2D(_line0)
>>> print ax.lines[0]
Line2D(_line0)

>>> #Same ID => same object
>>> id(lines[0]), id(ax.lines[0])
(216550352, 216550352)

如果您使用上面完成的操作调用plt.show(),您将看到一个包含一组轴和一行的图:

现在,虽然我们已经看到linesax.lines的内容是相同的,但非常重要的一点是要注意,lines变量引用的对象与ax.lines引用的对象不同,如下所示:

代码语言:javascript
复制
>>> id(lines), id(ax.lines)
(212754584, 211335288)

因此,从lines中删除元素不会对当前绘图造成任何影响,但是从ax.lines中删除元素会从当前绘图中删除该线。所以:

代码语言:javascript
复制
>>> #THIS DOES NOTHING:
>>> lines.pop(0)

>>> #THIS REMOVES THE FIRST LINE:
>>> ax.lines.pop(0)

因此,如果您要运行第二行代码,您将从当前绘图中删除包含在ax.lines[0]中的Line2D对象,它就会消失。请注意,这也可以通过ax.lines.remove()完成,这意味着您可以将Line2D实例保存在变量中,然后将其传递给ax.lines.remove()以删除该行,如下所示:

代码语言:javascript
复制
>>> #Create a new line
>>> lines.append(ax.plot(np.arange(1000)/2.0))
>>> ax.lines
[<matplotlib.lines.Line2D object at 0xce84bd0>,  <matplotlib.lines.Line2D object at 0xce84dx3>]

代码语言:javascript
复制
>>> #Remove that new line
>>> ax.lines.remove(lines[0])
>>> ax.lines
[<matplotlib.lines.Line2D object at 0xce84dx3>]

以上所有方法都适用于fig.axes,就像它适用于ax.lines一样

现在,真正的问题是。如果我们将包含在ax.lines[0]中的引用存储到一个weakref.ref对象中,然后尝试删除它,我们会注意到它不会被垃圾回收:

代码语言:javascript
复制
>>> #Create weak reference to Line2D object
>>> from weakref import ref
>>> wr = ref(ax.lines[0])
>>> print wr
<weakref at 0xb758af8; to 'Line2D' at 0xb757fd0>
>>> print wr()
<matplotlib.lines.Line2D at 0xb757fd0>

>>> #Delete the line from the axes
>>> ax.lines.remove(wr())
>>> ax.lines
[]

>>> #Test weakref again
>>> print wr
<weakref at 0xb758af8; to 'Line2D' at 0xb757fd0>
>>> print wr()
<matplotlib.lines.Line2D at 0xb757fd0>

引用仍然是活动的!为什么?这是因为wr中的引用所指向的Line2D对象还有另一个引用。还记得linesax.lines没有相同的ID,但却包含相同的元素吗?这就是问题所在。

代码语言:javascript
复制
>>> #Print out lines
>>> print lines
[<matplotlib.lines.Line2D object at 0xce84bd0>,  <matplotlib.lines.Line2D object at 0xce84dx3>]

To fix this problem, we simply need to delete `lines`, empty it, or let it go out of scope.

>>> #Reinitialize lines to empty list
>>> lines = []
>>> print lines
[]
>>> print wr
<weakref at 0xb758af8; dead>

所以,这个故事的寓意是,自己清理干净。如果您希望某个东西被垃圾收集,但它并没有被垃圾收集,那么您可能会在某个地方留下一个引用。

票数 78
EN

Stack Overflow用户

发布于 2012-03-28 03:29:37

我在不同的论坛上尝试了很多不同的答案。我猜这取决于你开发的机器。但是我用了这个语句

代码语言:javascript
复制
ax.lines = []

而且工作得很完美。我不使用cla(),因为它删除了我对绘图所做的所有定义

例如。

代码语言:javascript
复制
pylab.setp(_self.ax.get_yticklabels(), fontsize=8)

但我已经多次尝试删除这些行了。当我在删除的时候,我也使用弱引用库来检查对该行的引用,但是对我来说什么都不起作用。

希望这对其他人有效=D

票数 17
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4981815

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档