我在y轴上绘制了两个不同单位的数据集。有没有办法让刻度线和网格线在两个y轴上对齐?
第一张图片显示了我得到的内容,第二张图片显示了我想要的内容。
这是我用来绘制的代码:
import seaborn as sns
import numpy as np
import pandas as pd
np.random.seed(0)
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.plot(pd.Series(np.random.uniform(0, 1, size=10)))
ax2 = ax1.twinx()
ax2.plot(pd.Series(np.random.uniform(10, 20, size=10)), color='r')
答案 0 :(得分:25)
我不确定这是否是最漂亮的方式,但它确实用一行修复它:
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import pandas as pd
np.random.seed(0)
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.plot(pd.Series(np.random.uniform(0, 1, size=10)))
ax2 = ax1.twinx()
ax2.plot(pd.Series(np.random.uniform(10, 20, size=10)), color='r')
# ADD THIS LINE
ax2.set_yticks(np.linspace(ax2.get_yticks()[0], ax2.get_yticks()[-1], len(ax1.get_yticks())))
plt.show()
答案 1 :(得分:8)
我可以通过停用其中一个网格轴中的ax.grid(None)
来解决这个问题:
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import pandas as pd
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.plot(pd.Series(np.random.uniform(0, 1, size=10)))
ax2 = ax1.twinx()
ax2.plot(pd.Series(np.random.uniform(10, 20, size=10)), color='r')
ax2.grid(None)
plt.show()
答案 2 :(得分:8)
我写了这个函数,它采用Matplotlib轴对象ax1,ax2和float minresax1 minresax2:
def align_y_axis(ax1, ax2, minresax1, minresax2):
""" Sets tick marks of twinx axes to line up with 7 total tick marks
ax1 and ax2 are matplotlib axes
Spacing between tick marks will be a factor of minresax1 and minresax2"""
ax1ylims = ax1.get_ybound()
ax2ylims = ax2.get_ybound()
ax1factor = minresax1 * 6
ax2factor = minresax2 * 6
ax1.set_yticks(np.linspace(ax1ylims[0],
ax1ylims[1]+(ax1factor -
(ax1ylims[1]-ax1ylims[0]) % ax1factor) %
ax1factor,
7))
ax2.set_yticks(np.linspace(ax2ylims[0],
ax2ylims[1]+(ax2factor -
(ax2ylims[1]-ax2ylims[0]) % ax2factor) %
ax2factor,
7))
它计算并设置刻度,使得有七个刻度。最低刻度对应于当前最低刻度并增加最高刻度,使得每个刻度之间的间隔是minrexax1或minrexax2的整数倍。
为了使其一般,您可以通过将您看到的所有7
更改为刻度总数来设置所需的刻度总数,并将6
更改为刻度总数减1
我提出了一个拉请求,将其中的一些内容合并到matplotlib.ticker.LinearLocator中:
https://github.com/matplotlib/matplotlib/issues/6142
将来(也许是Matplotlib 2.0?),试试:
import matplotlib.ticker
nticks = 11
ax1.yaxis.set_major_locator(matplotlib.ticker.LinearLocator(nticks))
ax2.yaxis.set_major_locator(matplotlib.ticker.LinearLocator(nticks))
这应该只是工作并为两个y轴选择方便的刻度。
答案 3 :(得分:1)
此代码将确保来自两个轴的网格彼此对齐,而不必隐藏任一组中的网格线。在此示例中,它允许您匹配任何更精细的网格线。这基于@Leo的想法。希望它有所帮助!
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import pandas as pd
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.plot(pd.Series(np.random.uniform(0,1,size=10)))
ax2 = ax1.twinx()
ax2.plot(pd.Series(np.random.uniform(10,20,size=10)),color='r')
ax2.grid(None)
# Determine which plot has finer grid. Set pointers accordingly
l1 = len(ax1.get_yticks())
l2 = len(ax2.get_yticks())
if l1 > l2:
a = ax1
b = ax2
l = l1
else:
a = ax2
b = ax1
l = l2
# Respace grid of 'b' axis to match 'a' axis
b_ticks = np.linspace(b.get_yticks()[0],b.get_yticks()[-1],l)
b.set_yticks(b_ticks)
plt.show()
答案 4 :(得分:1)
这已经在一段时间前得到正确回答: trouble aligning ticks for matplotlib twinx axes
(这里给出的答案对于一般情况根本不起作用)
答案 5 :(得分:0)
如果你正在使用轴标签,由于刻度中数字的精确度,Leo的解决方案可以push them off the side。
所以除了像Leo的解决方案(这里重复)之外,
ax2.set_yticks(np.linspace(ax2.get_yticks()[0],ax2.get_yticks()[-1],len(ax1.get_yticks())))
您可以使用this answer中提到的autolayout
设置;例如,在您的脚本中,您可以更新rcParams
:
from matplotlib import rcParams
rcParams.update({'figure.autolayout': True})
在一些测试用例中,这似乎产生了预期的结果,输出中完全包含了排列的标记和标签。
答案 6 :(得分:0)
答案 7 :(得分:0)
我创建了一种方法来对齐多个y轴的刻度线(可能大于2个),并且在不同的轴上刻度可能不同。
有3个y轴,左边是一个蓝色,右边是绿色和红色。将3条曲线以相应的颜色绘制到y轴上。请注意,它们的数量级都非常不同。
@Test
public void splitByMultiple() {
String input = "aa|bb cc";
final List<String> asList = Arrays.asList(input.split("[ |]"));
assertThat(asList, contains("aa", "bb", "cc"));
}
表示蓝色,0
表示红色,2.2*1e8
表示绿色。那些是任意选择的。我正在做的是将每个y数组缩放到1-100的范围内,然后将所有缩放后的y值合并到一个数组中,并使用{{1} }。然后,使用相应的缩放比例来缩放这组新的滴答声,以获取每个轴的新滴答声。如果需要某些特定的对齐方式,则y数组在缩放之前会先移位,然后再移位回去。
在此处完成代码(关键功能是44
):
MaxNLocator