gpt4 book ai didi

python - 具有匹配网格线的双 y 轴

转载 作者:行者123 更新时间:2023-12-03 12:13:34 29 4
gpt4 key购买 nike

这个问题在这里已经有了答案:





How do I align gridlines for two y-axis scales using Matplotlib?

(7 个回答)


3年前关闭。




我想生成一个 matplotlib 折线图,其中两个变量显示在两个单独的 y 轴上,并带有匹配的网格线。除了匹配的网格线部分之外,这一切都非常简单。以下是一些可重现的片段,包括最佳尝试。一个完整的片段可以在最后找到。

具有初始图的可重现数据框

遵循 Adding a y-axis label to secondary y-axis in matplotlib 的建议我能够生产这个:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt


# Dataframe with some random numbers
np.random.seed(123)
rows = 4
df = pd.DataFrame(np.random.randint(90,110,size=(rows, 2)), columns=list('AB'))
datelist = pd.date_range(pd.datetime(2017, 1, 1).strftime('%Y-%m-%d'), periods=rows).tolist()
df['dates'] = datelist
df = df.set_index(['dates'])
df.index = pd.to_datetime(df.index)
df['B'] = df['A'] * np.random.uniform(0.6,1.4, size = 4)

# Plot 1
fig, ax = plt.subplots()
t = df.index
ax.plot(t, df['A'])
ax2 = ax.twinx()
ax2.plot(t, df['B'], color='red')
ax2.yaxis.grid(which="major", color='green', linestyle='--')

ax.legend(loc='upper left')
ax2.legend(loc='upper right')
plt.show()

地块 1

enter image description here

如您所见,matplotlib 为两个变量选择了合理的区间,但 y 轴的网格线不太匹配。遵循 Align secondary y-axis ticks with stripplot on primary x-axis 的建议我能够对齐它们,但这自然会遗漏一些值:

地块 2
# Plot 2
fig, ax = plt.subplots()
t = df.index
ax.plot(t, df['A'])
ax2 = ax.twinx()
ax2.plot(t, df['B'], color='red')
#--
ax2.set_ylim(ax.get_ylim())

ax2.yaxis.grid(which="major", color='green', linestyle='--')
ax.legend(loc='upper left')
ax2.legend(loc='upper right')
plt.show()

enter image description here

我的下一次尝试是使用 ax2int = ax2.get_ylim()[1] - ax2.get_ylim()[0] 检索辅助 y 轴的间隔。并将其除以主轴上的网格线数以使其匹配。然后按照 Changing the “tick frequency” on x or y axis in matplotlib 的建议进行操作使用 np.arange(start, stop, steps) .但我无法弄清楚如何完美匹配间隔,如下所示:
fig, ax = plt.subplots()
t = df.index
ax.plot(t, df['A'])
ax2 = ax.twinx()
ax2.plot(t, df['B'], color='red')

# The math
firstStep = ax.get_yticks()[1] - ax.get_yticks()[0]
ax2int = ax2.get_ylim()[1] - ax2.get_ylim()[0]
axSteps = len(ax.get_yticks())
newIntervals = ax2int / axSteps

# My best attempt
myticks = np.arange(min(df['B']), max(df['B']), newIntervals)
ax2.set(yticks=myticks)
ax2.yaxis.grid(which="major", color='green', linestyle='--')
ax.legend(loc='upper left')
ax2.legend(loc='upper right')

plt.show()

地块 3

enter image description here

任何建议都会很棒!也许 matplotlib 中已经有一些内置功能可以做这些事情?谢谢!

这是一个简单的复制粘贴的全部内容:
# Libraries
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt


# Dataframe with some random numbers
np.random.seed(123)
rows = 4
df = pd.DataFrame(np.random.randint(90,110,size=(rows, 2)), columns=list('AB'))
datelist = pd.date_range(pd.datetime(2017, 1, 1).strftime('%Y-%m-%d'), periods=rows).tolist()
df['dates'] = datelist
df = df.set_index(['dates'])
df.index = pd.to_datetime(df.index)
df['B'] = df['A'] * np.random.uniform(0.6,1.4, size = 4)

# Plot 1
fig, ax = plt.subplots()
t = df.index
ax.plot(t, df['A'])
ax2 = ax.twinx()
ax2.plot(t, df['B'], color='red')
ax2.yaxis.grid(which="major", color='green', linestyle='--')

ax.legend(loc='upper left')
ax2.legend(loc='upper right')
plt.show()
#%%

# Plot 2
fig, ax = plt.subplots()
t = df.index
ax.plot(t, df['A'])
ax2 = ax.twinx()
ax2.plot(t, df['B'], color='red')
#--
ax2.set_ylim(ax.get_ylim())

ax2.yaxis.grid(which="major", color='green', linestyle='--')
ax.legend(loc='upper left')
ax2.legend(loc='upper right')
plt.show()
#%%

# Plot 3
fig, ax = plt.subplots()
t = df.index
ax.plot(t, df['A'])
ax2 = ax.twinx()
ax2.plot(t, df['B'], color='red')

# The math
firstStep = ax.get_yticks()[1] - ax.get_yticks()[0]
ax2int = ax2.get_ylim()[1] - ax2.get_ylim()[0]
axSteps = len(ax.get_yticks())
newIntervals = ax2int / axSteps

# My best attempt
myticks = np.arange(min(df['B']), max(df['B']), newIntervals)
ax2.set(yticks=myticks)
ax2.yaxis.grid(which="major", color='green', linestyle='--')
ax.legend(loc='upper left')
ax2.legend(loc='upper right')

plt.show()

最佳答案

对齐 yticks手动设置第二个轴很棘手,因为 (a) 并非所有 yticks显示(例如做 print(ax.get_yticks()) 并与您的绘图进行比较)和 (b) 因为 set_yticks()也会影响 ylims .更换您的部分 #The math#My best attempt以下对我有用:

# The math
ylim1 = ax.get_ylim()
len1 = ylim1[1]-ylim1[0]
yticks1 = ax.get_yticks()
rel_dist = [(y-ylim1[0])/len1 for y in yticks1]
ylim2 = ax2.get_ylim()
len2 = ylim2[1]-ylim2[0]
yticks2 = [ry*len2+ylim2[0] for ry in rel_dist]

#My best attempt
ax2.set_yticks(yticks2)
ax2.set_ylim(ylim2) #<-- this line is needed to re-adjust the limits to the original values
ax.yaxis.grid(which="major", color='black', linestyle='-')
ax2.yaxis.grid(which="major", color='green', linestyle='--')
ax.legend(loc='upper left')
ax2.legend(loc='upper right')

结果图如下所示:

enter image description here

希望这可以帮助。

关于python - 具有匹配网格线的双 y 轴,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48090998/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com