2014-11-05 87 views
15

我在y轴上绘制两个不同单位的数据集。有没有办法让蜱和网格线在两个y轴上对齐?如何使用Matplotlib为两个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') 

Example of unwanted behavior

Example of wanted behavior

+0

你在找'ax2.set_ylim((10,20))'? – farenorth 2014-11-05 13:18:28

+0

我正在寻找一个通用的方法来做到这一点。即如果我得到任何两个数据集,我如何以网格线重合的方式设置图。 – 2014-11-05 13:32:17

+0

你只需要通过设置你的极限和刻度间距手动做到这一点。 – 2014-11-05 19:00:42

回答

14

我不知道这是否是做的最漂亮的方式,但它确实有一个线修复:

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() 
+5

不要太挑剔,但蓝线现在位于网格之下,红线位于网格之上。所以我在ax2.set_yticks行后面添加'ax2.grid(None)'并获得相同的刻度和网格线,但是现在这两行都在网格之上。 – benten 2016-04-09 18:35:59

4

我可以在grid`s之一停用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() 

Figure Result

+0

不幸的是,这会从一个轴移除网格,而不是对齐刻度和网格。在你的例子中,你碰巧在两个轴上的同一个位置上有刻度线,但是如果另一个轴在不同的位置上,那个轴的刻度线就不会与网格对齐。 – 2015-03-19 07:53:40

+0

但它回答你的问题,并以你想要的方式重现这个数字。你可以对你的问题更具体。 – arnaldo 2015-03-19 12:14:46

+0

运行你的代码几次,你会明白我的意思。 – 2015-03-19 12:27:36

6

我写了这个函数,它Matplotlib轴对象AX1,AX2,并浮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轴。

+1

如果我们想要使用matplotlib.ticker,我们如何自动获得刻度数而不是指定nticks? – Spinor8 2017-07-21 09:28:05

0

如果您使用的是轴标签,由于刻度中数字的精确性,因此Leo的解决方案可能为push them off the side

所以除了像狮子座的解决方案(这里不再重复),

ax2.set_yticks(np.linspace(ax2.get_yticks()[0],ax2.get_yticks()[-1],len(ax1.get_yticks()))) 

可以使用autolayout设置,如this answer提到的;例如,此前在你的脚本可以更新rcParams

from matplotlib import rcParams 
rcParams.update({'figure.autolayout': True}) 

在一些测试情况下,这似乎产生预期的结果,具有完全包含在输出都一字排开向上蜱和标签。

0

该代码将确保来自两个轴的网格彼此对齐,而不必隐藏两个网格中的网格线。在这个例子中,它允许你匹配具有更细网格线的任何一个。这建立在@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() 
0

我有同样的问题,除了这是第二个x轴。我解决了等于我的二次X轴设定为低于我主axis.The例的限制是不等于设置第二轴的限位到第一:ax2 = ax.twiny() enter image description here

一旦予设定第二轴的限位等于第一个ax2.set_xlim(ax.get_xlim())这里是我的结果: enter image description here