gpt4 book ai didi

python - 在 Matplotlib 中将一条曲线正好放在另一条曲线的下方

转载 作者:行者123 更新时间:2023-12-04 08:53:46 25 4
gpt4 key购买 nike

我在 Matplotlib 中有两条曲线,我想让它们正好在彼此的下方。我天真的方法是将一条曲线的值减少一个常数因子。奇怪的是,在 Matplotlib(与 Excel 相对)中,创建的曲线有一些偏差,并且并不总是在彼此下方。
这是我的代码:

from matplotlib import pyplot as plt
from scipy.interpolate import interp1d
import numpy as np
load = [0.0, 0.1, 0.5, 0.7, 0.4, 0.5, 0.4, 0.3, 0.4, 0.5, 0.65, 0.75, 0.8, 0.65, 0.15, 0.55, 0.1, 0.4, 0.0, 0.25, 0.25, 0.35, 0.6, 0.25, 0.05]
#demand = [0.35, 0.25, 0.15, 0.1, 0.1, 0.2, 0.40, 0.50, 0.50, 0.40, 0.40, 0.47, 0.47, 0.40, 0.35, 0.35, 0.4, 0.5, 0.65, 0.7, 0.65, 0.5, 0.4, 0.35, 0.25]
help = 0.025;
demand = [0.0-help, 0.1-help, 0.5-help, 0.7-help, 0.4-help, 0.5-help, 0.4-help, 0.3-help, 0.4-help, 0.5-help, 0.65-help, 0.75-help, 0.8-help, 0.65-help, 0.15-help, 0.55-help, 0.1-help, 0.4-help, 0.0-help, 0.25-help, 0.25-help, 0.35-help, 0.6-help, 0.25-help, 0.05-help]
hours = list(range(25)) # [0, 1, 2, ... 22, 23, 24]
labels = [f'{h:02d}:00' for h in hours] # ["00:00", "01:00", ... "23:00", "24:00"]


f = interp1d(hours, load, kind='cubic')
f2 = interp1d(hours, demand, kind='cubic')


xnew = np.linspace(0, 24, num=500, endpoint=True)

plt.xticks(np.arange(0, 25, step=1)) # Set label locations.
plt.xticks(np.arange(25), labels) # Set text labels.
plt.xticks(np.arange(25), labels, rotation=90)

plt.plot(hours, load, 'o', xnew, f(xnew), '-', xnew, f2(xnew), '--')
#plt.legend(['data', 'linear', 'cubic'], loc='best')
plt.ylabel("Electrical power in W", fontsize=14, labelpad=8)
plt.xlabel("Time of day", fontsize=14, labelpad=8)
plt.show()


plt.xticks(np.arange(0, 25, step=1)) # Set label locations.
plt.xticks(np.arange(25), labels) # Set text labels.
plt.xticks(np.arange(25), labels, rotation=90)
plt.xlim(xmin=0.0)

xnew = np.linspace(0, 24, num=500, endpoint=True)
plt.xticks(np.arange(0, 25, step=1)) # Set label locations.
plt.xticks(np.arange(25), labels) # Set text labels.
plt.xticks(np.arange(25), labels, rotation=90)


plt.plot(xnew, f(xnew), color="gold", linewidth=3)
plt.plot(xnew, f2(xnew), color="green", linewidth=3)
#plt.fill_between(xnew, f(xnew), color="gold", alpha=0.30, edgecolor=None)
#plt.fill_between(xnew, f2(xnew), color="red", alp_ha=0.30, edgecolor=None)

plt.legend( ['Electricity generation', 'Electricity demand'], bbox_to_anchor=(0.5, 1.2), loc='upper center' )
plt.ylabel("Electrical power", fontsize=14, labelpad=8)
plt.xlabel("Time of day", fontsize=14, labelpad=8)
plt.tick_params(labelleft=False)
plt.savefig('Generation_Demand_DSM.png', edgecolor='black', dpi=400, bbox_inches='tight')
plt.show()
在这里你会看到结果。我举例说明了一些曲线几乎相同的区域(因此一个与另一个相距不远)和偏差过高的区域。 enter image description here
任何想法我怎么能以“干净”的方式做到这一点?我会很感激每一条评论。
更新:因为这似乎是一项艰巨的任务,我想知道,如果有可能以某种方式在 Matplotlib 中获得具有透明背景的曲线,这样我就可以创建曲线,然后手动将其放置在原始曲线下(通过使用例如油漆)?
所以在 Matplotlib 中没有选项可以只创建具有透明背景的曲线?

最佳答案

正如许多人已经在评论中建议的那样,当您减去 y 值时,只有 y 轴发生了变化,而 x 轴保持不变,因此不会产生您想要的效果。这主要是因为曲线的斜率不同。但是,我们可以使用斜率信息人为地创建偏移。
效果需要进一步细化和微调才能获得准确的位移。我在这里分享代码作为起点。

from matplotlib import pyplot as plt
from scipy.interpolate import interp1d
import numpy as np
load = [0.0, 0.1, 0.5, 0.7, 0.4, 0.5, 0.4, 0.3, 0.4, 0.5, 0.65, 0.75, 0.8, 0.65, 0.15, 0.55, 0.1, 0.4, 0.0, 0.25, 0.25, 0.35, 0.6, 0.25, 0.05]
shift = 0.02;
demand = [l-shift for l in load]
hours = list(range(25)) # [0, 1, 2, ... 22, 23, 24]
labels = [f'{h:02d}:00' for h in hours] # ["00:00", "01:00", ... "23:00", "24:00"]

fig = plt.figure(figsize=(20,10))
f = interp1d(hours, load, kind='quadratic')
f2 = interp1d(hours, demand, kind='quadratic')


xnew = np.linspace(0, 24, num=500, endpoint=True)

plt.xticks(np.arange(0, 25, step=1)) # Set label locations.
plt.xticks(np.arange(25), labels) # Set text labels.
plt.xticks(np.arange(25), labels, rotation=90)
plt.xlim(xmin=0.0)

xnew = np.linspace(0, 24, num=500, endpoint=True)
plt.xticks(np.arange(0, 25, step=1)) # Set label locations.
plt.xticks(np.arange(25), labels) # Set text labels.
plt.xticks(np.arange(25), labels, rotation=90)

xshift = xnew+np.concatenate(([0],np.diff(f(xnew))*7))

plt.plot(xnew, f(xnew), color="gold", linewidth=5)
plt.plot(xshift, f2(xnew), color="green", linewidth=5)

# plt.fill_between(xnew+np.concatenate(([0],np.diff(f(xnew))*7)),
# f(xnew)-0.02, f(xnew), color="gold", alpha=0.30, edgecolor=None)
#plt.fill_between(xnew, f2(xnew), color="red", alp_ha=0.30, edgecolor=None)

plt.legend( ['Electricity generation', 'Electricity demand'], bbox_to_anchor=(0.5, 1.2), loc='upper center' )
plt.ylabel("Electrical power", fontsize=14, labelpad=8)
plt.xlabel("Time of day", fontsize=14, labelpad=8)
plt.tick_params(labelleft=False)
plt.savefig('Generation_Demand_DSM.png', edgecolor='black', dpi=400, bbox_inches='tight')
plt.show()
注释:
  • 我还使用列表理解简化了您的需求值分配。
  • 斜率是使用 np.diff 获得的。斜率还处理 +ve 和 -ve 方向,因此可以直接用于移动绘图。
  • 乘数用于调整间距。
  • 要微调绘图,您可以针对不同的方向和斜率阈值使用不同的乘数。

  • 这是使用上述代码获得的输出。哈。
    Plot
    更新1:
    使用 matplotlib 的透明背景保存绘图
    根据 OP 的要求,如果您只想生成没有其他绘图元素的绘图,则可以通过以下代码更改来执行此操作:
    # plt.plot(xnew, f(xnew), color="gold", linewidth=5)
    plt.plot(xshift, f2(xnew), color="green", linewidth=5)

    # plt.fill_between(xnew+np.concatenate(([0],np.diff(f(xnew))*7)),
    # f(xnew)-0.02, f(xnew), color="gold", alpha=0.30, edgecolor=None)
    #plt.fill_between(xnew, f2(xnew), color="red", alp_ha=0.30, edgecolor=None)

    # plt.legend( ['Electricity generation', 'Electricity demand'], bbox_to_anchor=(0.5, 1.2), loc='upper center' )
    # plt.ylabel("Electrical power", fontsize=14, labelpad=8)
    # plt.xlabel("Time of day", fontsize=14, labelpad=8)
    # plt.tick_params(labelleft=False)

    plt.xticks([])
    plt.yticks([])

    plt.gca().spines['top'].set_visible(False)
    plt.gca().spines['right'].set_visible(False)
    plt.gca().spines['left'].set_visible(False)
    plt.gca().spines['bottom'].set_visible(False)

    plt.savefig('Generation_Demand_DSM_second.png', edgecolor='none', dpi=400, bbox_inches='tight', transparent=True)
    plt.show()
    它会生成这样的输出(请注意,这里以白色背景呈现,但原始 png 将保留透明度):
    Transparent plot
    现在您可以使用原始设置和第二条曲线创建第一条曲线,如上所示。然后,您可以使用油漆(或类似工具)将第二条曲线叠加在第一条曲线上,并根据需要进行操作。 HTH
    更新 2:
    使用 Inkscape 进行编辑
    如果您使用的是inkscape,则当您将图形另存为pdf时,该图将变得非常可编辑。您可以保留所有原始设置,只更改 savefig 行,如下所示:
    plt.savefig('Generation_Demand_DSM_second.pdf', bbox_inches='tight')
    生成的 pdf 可在inkscape 中完全编辑。您只需要像打开任何其他文件一样打开它(大多数默认设置应该可以工作,或者您可以在打开的对话框中选择 poppler 导入)。每个元素都可以单独选择,如此处的屏幕截图所示:
    inkscape screenshot
    您可以根据需要操作输出。

    关于python - 在 Matplotlib 中将一条曲线正好放在另一条曲线的下方,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63954726/

    25 4 0