【问题标题】:How do I make matplotlib generate a single plot instead of a plot for each data point?如何让 matplotlib 为每个数据点生成一个图而不是一个图?
【发布时间】:2016-10-06 08:14:43
【问题描述】:

我正在尝试生成三个图,每个图都使用相同的输入。 当我运行我的代码时,我会为每个 x 输入生成一个图,而不是由它们的所有数据点组成的三个图。

请参阅下面的代码:

xlist = np.linspace(0, 2.5)

for name, f, df in zip(func_names, funcs, diff_funcs):
 for x in xlist:
  plt.plot(diff(f, x, h=0.01), 'bs', forwdiff(f, x, h=0.01), 'g^')
  plt.title(name)
  plt.xlabel('x')
  plt.ylabel('f(x)')
  bluesq = plt.Line2D([], [], color='blue', marker='s',
                      markersize=15, label='Centered Difference')
  greentr = plt.Line2D([], [], color='green', marker='^',
                      markersize=15, label='Forward Difference')
  l1 = plt.legend(handles = [bluesq], loc=1)
  l2 = plt.legend(handles = [greentr], loc=4)
  plt.gca().add_artist(l1)
  plt.gca().add_artist(l2)
  plt.show()

完整代码:

import numpy as np
import matplotlib.pyplot as plt

print("---Forward Diff---")

def forwdiff(f, x, h=1e-5):
     """
     Returns the forward derivative of a function f
     """
     return 1 / (h) * (f(x + h) - f(x))

from math import exp, cos, sin, pi, log


f1 = lambda x: exp(-2 * x ** 2)
df1 = lambda x: -4 * x * exp(-2 * x ** 2)
f2 = lambda x: cos(x)
df2 = lambda x: -sin(x)
f3 = lambda x: sin(x)
df3 = lambda x: cos(x)

funcs = [f1, f2, f3]
diff_funcs = [df1, df2, df3]
func_names = ['exp(-2x^2)', 'cos(x)', 'sin(x)']
values = [2, 0.6, 0.6]

print '%10s %8s %8s %8s' % ('function', 'exact', 'approx', 'error')

for name, f, df, x in zip(func_names, funcs, diff_funcs, values):
    exact = df(x)
    approx = forwdiff(f, x, h=0.01)
    error = abs(exact - approx)
    print '%10s %.6f %.6f %.6f' % (name, exact, approx, error)


def test_forwdiff():
    success = 6 - forwdiff(lambda x: x**2, 3, h=0.01) < 0.00000000001
    msg = "test_forwdiff failed"
    assert success, msg

print("---Centered Diff---")


def diff(f, x, h=1e-5):
     """
     Returns the derivative of a function f
     """
     return 1 / (2 * h) * (f(x + h) - f(x - h))

from math import exp, cos, sin, pi, log

f1 = lambda x: exp(-2 * x ** 2)
df1 = lambda x: -4 * x * exp(-2 * x ** 2)
f2 = lambda x: cos(x)
df2 = lambda x: -sin(x)
f3 = lambda x: sin(x)
df3 = lambda x: cos(x)

funcs = [f1, f2, f3]
diff_funcs = [df1, df2, df3]
func_names = ['exp(-2x^2)', 'cos(x)', 'sin(x)']
values = [2, 0.6, 0.6]

print '%10s %8s %8s %8s' % ('function', 'exact', 'approx', 'error')

for name, f, df, x in zip(func_names, funcs, diff_funcs, values):
    exact = df(x)
    approx = diff(f, x, h=0.01)
    error = abs(exact - approx)
    print '%10s %.6f %.6f %.6f' % (name, exact, approx, error)


def test_diff():
    success = 6 - diff(lambda x: x**2, 3, h=0.01) < 0.00000000001
    msg = "test_diff failed"
    assert success, msg

xlist = np.linspace(0, 2.5)

for name, f, df in zip(func_names, funcs, diff_funcs):
    for x in xlist:
     plt.plot(diff(f, x, h=0.01), 'bs', forwdiff(f, x, h=0.01), 'g^')
     plt.title(name)
     plt.xlabel('x')
     plt.ylabel('f(x)')
     bluesq = plt.Line2D([], [], color='blue', marker='s',
                          markersize=15, label='Centered Difference')
     greentr = plt.Line2D([], [], color='green', marker='^',
                          markersize=15, label='Forward Difference')
     l1 = plt.legend(handles = [bluesq], loc=1)
     l2 = plt.legend(handles = [greentr], loc=4)
     plt.gca().add_artist(l1)
     plt.gca().add_artist(l2)
     plt.show()

所以,我发现 plot() 需要将整个 x_list 和 y_list 作为参数。

这让我明白了:

    xlist = np.linspace(0, 2.5)

for name, f in zip(func_names, funcs):
    ylist = [forwdiff(f, x, h=0.01) for x in xlist]
    plt.plot(xlist, ylist, 'g^')

    ylist = [diff(f, x, h=0.01) for x in xlist]
    plt.plot(xlist, ylist, 'bs')
    plt.title(name)

plt.xlabel('x')
plt.ylabel('f(x)')
bluesq = plt.Line2D([], [], color='blue', marker='s',
                          markersize=15, label='Centered Difference')
greentr = plt.Line2D([], [], color='green', marker='^',
                          markersize=15, label='Forward Difference')
l1 = plt.legend(handles = [bluesq], loc=1)
l2 = plt.legend(handles = [greentr], loc=4)
plt.gca().add_artist(l1)
plt.gca().add_artist(l2)
plt.show()

这正确地将所有输入绘制到一个图上,但我试图生成三个图。每个 f 输入一个。给出的代码调用 f 和 df 并为每个生成一个图,但将它们绘制到同一个窗口。我如何将该图分成三个不同的窗口,显示每个 f 的 forwdiff 和 diff?

对不起,如果这是一个愚蠢的问题,我的背景不是计算机科学/编程。

我想将图分成三个 forwdiff 和 diff 图,分别对应 exp(-2x2)、cos(x) 和 sin(x)。

【问题讨论】:

标签: python matplotlib plot


【解决方案1】:

所以,我发现 plot() 需要将整个 x_list 和 y_list 作为参数。

这让我明白了:

    xlist = np.linspace(0, 2.5)

for name, f in zip(func_names, funcs):
    ylist = [forwdiff(f, x, h=0.01) for x in xlist]
    plt.plot(xlist, ylist, 'g^')

    ylist = [diff(f, x, h=0.01) for x in xlist]
    plt.plot(xlist, ylist, 'bs')
    plt.title(name)

plt.xlabel('x')
plt.ylabel('f(x)')
bluesq = plt.Line2D([], [], color='blue', marker='s',
                          markersize=15, label='Centered Difference')
greentr = plt.Line2D([], [], color='green', marker='^',
                          markersize=15, label='Forward Difference')
l1 = plt.legend(handles = [bluesq], loc=1)
l2 = plt.legend(handles = [greentr], loc=4)
plt.gca().add_artist(l1)
plt.gca().add_artist(l2)
plt.show()

这正确地将所有输入绘制到一个图上,但我试图生成三个图。每个 f 输入一个。给出的代码调用 f 和 df 并为每个生成一个图,但将它们绘制到同一个窗口。我如何将该图分成三个不同的窗口,显示每个 f 的 forwdiff 和 diff?

对不起,如果这是一个愚蠢的问题,我的背景不是计算机科学/编程。

我想将这些图分成三个 forwdiff 和 diff 图,分别用于 exp(-2x2)、cos(x) 和 sin(x)。

【讨论】:

    【解决方案2】:

    离开你的答案,你正在寻找这样的东西:

    # axarr is an array of axes objects (1 row, 3 columns)
    fig, axarr = plt.subplots(1, 3)
    for ax, name, f in zip(ax, func_names, funcs):
        for df, dfname in zip((forwdiff, diff), ('forward', 'central')):
            ylist = [df(f, x, h=0.01) for x in xlist]
            ax.plot(xlist, ylist, 'g^', label=dfname)
    
        ax.set_title(name)
        # either set the axes labels here so all axes get them
        #ax.set_xlabel('x')
        #ax.set_ylabel('f(x)')
        # similarly, you can add a legend to each plot here
        #ax.legend(loc='upper right')
    
    # or set axes labels here:
    # all plots get x labels
    [ax.set_xlabel('x') for ax in axarr]
    # only the left most plot gets a ylabel
    axarr[0].set_ylabel('f(x)')
    
    # set only one legend and make it outside the rightmost plot
    axarr[-1].legend(loc='upper left', bbox_to_anchor=(1.02, 1))
    # move subplots over so you can see the legend
    fig.subplots_adjust(right=0.8)
    
    plt.show()
    

    您可能想查看numpy.gradient,它可以以矢量化方式计算导数。这样您就可以执行以下操作:

    xlist = np.linspace(0, 2.5)
    dx = np.gradient(xlist)
    dydx = np.gradient(f(xlist), dx)
    

    【讨论】:

      猜你喜欢
      • 2016-10-10
      • 2019-11-05
      • 1970-01-01
      • 1970-01-01
      • 2015-09-06
      • 1970-01-01
      • 1970-01-01
      • 2011-05-15
      • 1970-01-01
      相关资源
      最近更新 更多