【问题标题】:Display two Sympy plots as two Matplotlib subplots将两个 Sympy 图显示为两个 Matplotlib 子图
【发布时间】:2017-10-18 13:04:12
【问题描述】:

这段代码

from sympy import *
x=Symbol('x')
p1 = plot(x**2,(x,-2,2))
p2 = plot(x**3,(x,-2,2))

产生两个单独的图。

我想用 matplotlib 将它们显示为子图,而不是两个单独的图:

import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)
plt.show()

如何添加p1p2,以便它们在matplotlib 图中显示为子图?

【问题讨论】:

  • 我可能错了。但 sympy 的情节似乎没有采用ax 参数,而且一切似乎都基于数字。我认为 matplotlib 的状态仍然是:合并多个图形至少是 hacky,不推荐。 (对于这个例子,不直接使用 mpl 对我来说也没有多大意义;但对于你的实际任务可能会有所不同)。

标签: matplotlib sympy


【解决方案1】:

问题在于 sympy Plot 创建了自己的图形和轴。它并不意味着绘制到现有的轴。

但是,您可以在显示 sympy 图之前将绘图所绘制的坐标轴替换为现有坐标轴。

from sympy import Symbol,plot
import matplotlib.pyplot as plt

def move_sympyplot_to_axes(p, ax):
    backend = p.backend(p)
    backend.ax = ax
    backend.process_series()
    backend.ax.spines['right'].set_color('none')
    backend.ax.spines['bottom'].set_position('zero')
    backend.ax.spines['top'].set_color('none')
    plt.close(backend.fig)


x=Symbol('x')
p1 = plot(x**2,(x,-2,2), show=False)
p2 = plot(x**3,(x,-2,2), show=False)


fig, (ax,ax2) = plt.subplots(ncols=2)
move_sympyplot_to_axes(p1, ax)
move_sympyplot_to_axes(p2, ax2)

plt.show()

【讨论】:

  • 这是我以后需要记住的。我已经检查了那些后端属性,但无法使用它们。你对 hacky 的定义是什么?不好的代码或担心即将发生的 matplotlib 更改?
  • @sascha 不,这在 matplotlib 方面很好。 hacky 我的意思是实际上没有任何 API 可以使用。该解决方案首先阻止 sympy “后端”绘制任何内容,然后人为地替换其属性之一,然后手动调用其 show 方法将执行的部分操作。所以,猴子补丁也很hacky。
  • 这似乎在 Sympy 1.5 上被打破了,至少对我来说。我不得不用以下内容替换backend.process_series()backend._process_series(backend.parent._series, ax, backend.parent)
【解决方案2】:

我的解决方案没有直接将p1p2 添加到子图中。但是它们的 (x,y) 坐标会被捕获并使用。

import matplotlib.pyplot as plt
from sympy import symbols
import numpy as np

from sympy import symbols
from sympy.plotting import plot

# part 1
# uses symbolic plot of functions
x = symbols('x')

#p1, p2 = plot(x**2, x**3, (x, -2, 2))

# this plot will not show ...
# only produce 2 curves
p1, p2 = plot((x**2, (x, -2, 2)), \
                (x**3, (x, -2, 2)), \
                show=False)

# collect (x,y)'s of the unseen curves 
x1y1 = p1.get_points()  # array of 2D
x2y2 = p2.get_points() 

# part 2
# uses regular matplotlib to plot the data

fig = plt.figure(figsize=(8, 5))
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)

# do subplot 1 
ax1.plot(x1y1[0], x1y1[1], 'g')  # plot x**2 in green
ax1.set_xlim([-2, 2])
ax1.set_xlabel('X1')
ax1.set_ylabel('Y1')
ax1.set_title('Line1')  # destroyed by another .title(); axis metho1

# do subplot 2
ax2.plot(x2y2[0], x2y2[1], 'r')  # plot x**3 in red
ax2.set_xlim([-2, 2])
ax2.set_xlabel('X2')
ax2.set_ylabel('Y2')
ax2.set_title('Line2')

fig.subplots_adjust(wspace=0.4) # set space between subplots

plt.show()

结果图:

【讨论】:

  • 虽然不那么普遍,也许不是 OP 所要求的,但我认为在某些情况下这是可行的替代方案!
  • 我试图在一个图中画一个圆圈,但 get_points 不太有效。
  • @DipanMehta 请将其作为一个新问题提出,以便更多人(包括我)可以提供帮助。
【解决方案3】:

您可以简单地使用 plotgrid 在一个图中获得 2 个或更多图。
另见:sympy.plotting.PlotGrid()

这是一个工作示例:

import sympy as sp
from matplotlib import pyplot as plt

# define functions
x = symbols('x')
f = sin(x)
g = cos(x)

# create separate plots
p1 = plot(f, show=False, xlim=(-pi, pi), line_color='blue', legend=True)
p2 = plot(g, show=False, xlim=(-pi, pi), line_color='red', legend=True)

# create a plotgrid with 2 rows and 1 column
plotgrid = sp.plotting.PlotGrid(2, 1, p1, p2, show=False, size=(5., 3.5))
plotgrid.show()

结果图:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-21
    • 1970-01-01
    • 2020-03-03
    • 1970-01-01
    • 1970-01-01
    • 2021-04-11
    相关资源
    最近更新 更多