【发布时间】:2021-09-24 11:16:22
【问题描述】:
我目前想用 Python 在同一个图形上绘制多个指数函数(大约 100 个)。
我有参数a 和b 的指数函数值:
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 的倍数,范围从1 到10,以0.1 为步长。我还想在同一图表上绘制nth 和n-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