【问题标题】:Plotting multiple curves and intersection points using for loop?使用for循环绘制多条曲线和交点?
【发布时间】:2021-09-24 11:16:22
【问题描述】:

我目前想用 Python 在同一个图形上绘制多个指数函数(大约 100 个)。

我有参数ab 的指数函数值:

def exponenial_func(x, a, b):
    return a * np.exp(-b * x)


popt1 = [8.05267292e+03, 1.48857925e+00]
x = np.linspace(0, 15, 30000)
yfun = exponenial_func(x, *popt1)

我现在希望将exponential_func 绘制成popt1 的倍数,范围从110,以0.1 为步长。我还想在同一图表上绘制nthn-1th 曲线之间的交点(如果可能的话)。

到目前为止,我已经尝试了下面的代码,但这不起作用:

import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import scipy.optimize as optimize
from scipy.optimize import curve_fit
import matplotlib.pylab as pl


def exponenial_func(x, a, b):
    return a * np.exp(-b * x)


x = np.linspace(0, 15, 30000)

popt1 = [8.05267292e+03, 1.48857925e+00]

# use a loop to plot multiples of popt1 applied to
# exponenial_func from 1x to 10x in steps of
# 0.1x (100 plots total) - create envelope
# --------------------------------------

# create color palette
# -----------------
n = 100
# choose a matplotlib color map
colors = pl.cm.gist_heat(np.linspace(0, 1, n))
# -----------------
fig = plt.figure(figsize=(4.5, 3.6))
ax = fig.add_subplot(1, 1, 1)
ax.set_ylim([1e2, 1e5])
ax.set_xlim([0, 1])

ax.set_yscale("log")

ax.spines['right'].set_visible(True)
ax.spines['top'].set_visible(True)
ax.spines['left'].set_visible(True)
ax.spines['bottom'].set_visible(True)
ax.set_xlabel('x')
ax.set_ylabel('y')

# enable minor ticks
ax.minorticks_on()

# put grid behind curves
ax.set_axisbelow(True)

ax.xaxis.grid(True, which='minor')
ax.xaxis.set_minor_formatter(matplotlib.ticker.NullFormatter())

# turn on major grid
ax.grid(b=True, which='major', color='black', linestyle='-', zorder=1, linewidth=0.4, alpha=0.12)

# turn on minor grid
ax.grid(b=True, which='minor', color='black', linestyle='-', zorder=1, linewidth=0.4, alpha=0.12)

ax.tick_params(direction='out', axis='both', which='both', pad=4)
ax.xaxis.set_ticks_position('bottom')

for i in np.arange(1, 10, n):
    popt_i = i * popt1
    # find the previous set of paramets (cannot multiply list by float?)
    popt_prev = (i - 10 / n) * popt1
    yfun_i = exponenial_func(x, *popt_i)
    yfun_prev = exponenial_func(x, *popt_prev)
    idx_i = np.argwhere(np.diff(np.sign(yfun_i - yfun_prev))).flatten()

    ax.plot(x, yfun_i, zorder=1, c=colors[i], linewidth=1, alpha=1)
    ax.scatter(x[idx_i], yfun_i[idx_i], s=4, alpha=1, zorder=4, color="black")

plt.savefig('test.png', dpi=300, bbox_inches='tight', format='png')

如果有人出线:

#yfun_prev = exponenial_func(x, *popt_prev)
#idx_i = np.argwhere(np.diff(np.sign(yfun_i - yfun_prev))).flatten()
#ax.scatter(x[idx_i], yfun_i[idx_i], s=4, alpha=1, zorder=4, color="black")

为了删除查看交叉点的代码的任何部分,代码运行,但我只得到这个作为一个情节:

如果代码中保留以上几行,则会出现以下错误:

File "envelope.py", line 63, in <module>
    popt_prev = (i - 10 / n) * popt1
TypeError: can't multiply sequence by non-int of type 'numpy.float64'

有谁知道如何在 Python 中实现这一点?

【问题讨论】:

  • 我刚刚编辑了那个,谢谢!但不,这不是导致代码问题的原因。
  • 不用担心。我只是想确定这是否与问题有关。
  • 您可以将第 63 行更改为 popt_prev = [(i - 10 / n) * _ for _ in popt1] 以摆脱 can't multiply sequence by non-int 错误。
  • 另外,你的循环只运行了 1 次,因为 np.arange(1, 10, n) == array([1]) 代表 n = 100。我猜你的意思是np.arange(1, n, 10)
  • 最后一个猜测popt_i = i * popt1 应该替换为 popt_i = [i * _ for _ in popt1]

标签: python numpy for-loop matplotlib plot


【解决方案1】:

下面的代码总结了我所有的cmets,修正了你原始代码中的一些小错误和一些视觉参数,将产生如下图像:

import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.pylab as pl


def fx(x, a, b):
    return a * np.exp(-b * x)


n = 100
x = np.linspace(0, 15, 30000)
popt1 = np.array([8.05267292e+03, 1.48857925e+00])

colorspace = pl.cm.prism(np.linspace(0, 1, n))

fig = plt.figure(figsize=(4.5, 3.6))
ax = fig.add_subplot(1, 1, 1)
ax.set_ylim([1e2, 1e5])
ax.set_xlim([0, 1])

ax.set_yscale("log")

ax.spines[:].set_visible(True)
ax.spines[:].set_linewidth(0.4)

ax.set_xlabel('x')
ax.set_ylabel('f(x) = a * exp(-b * x)')

ax.minorticks_on()

ax.set_axisbelow(True)

ax.xaxis.grid(True, which='minor')
ax.xaxis.set_minor_formatter(matplotlib.ticker.NullFormatter())

ax.grid(True, which='major', alpha=.75, color='pink', ls='solid', lw=.5, zorder=1)
ax.grid(True, which='minor', alpha=.75, color='pink', ls='solid', lw=.5, zorder=1)

ax.tick_params(direction='out', axis='both', pad=4, width=.5, which='both')

ax.xaxis.set_ticks_position('bottom')

for i in range(n):
    popt_i = np.multiply(popt1, 1 + i // 10)
    popt_prev = np.multiply(popt1, i - 10 / n)
    yfun_i = fx(x, *popt_i)
    yfun_prev = fx(x, *popt_prev)
    idx_i = np.argwhere(np.diff(np.sign(yfun_i - yfun_prev))).flatten()
    ax.plot(x, yfun_i, c=colorspace[i], lw=.25, zorder=2)
    ax.scatter(x[idx_i], yfun_i[idx_i], s=.5, zorder=3)

plt.savefig('test.png', dpi=300, bbox_inches='tight', format='png')

【讨论】:

    猜你喜欢
    • 2019-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-31
    • 1970-01-01
    • 2020-11-10
    • 1970-01-01
    相关资源
    最近更新 更多