Pyplot,将2个数据集绘制成一个图,跳过y轴的一部分

时间:2011-06-24 21:12:38

标签: python matplotlib

我正在使用pylab.plot()将不同的数据集绘制到一个图形中,效果很好。但是,一个数据集的值介于0%和25%之间,另一个数据集的值介于75%和100%之间。我想在y轴上跳过30%到70%以节省一些空间。您对pyplot如何使用有任何建议吗?

编辑:

为清楚起见,我添加了以下图表。我想在y轴上跳过30%到60%,这样红线和绿线就会越来越近。

graphic

3 个答案:

答案 0 :(得分:1)

解决方案基于Space_C0wb0ys post。

fig = pylab.figure()
ax = fig.add_subplot(111)
ax.plot( range(1,10), camean - 25, 'ro-' )
ax.plot( range(1,10), oemean , 'go-' )
ax.plot( range(1,10), hlmean , 'bo-' ) 
ax.set_yticks(range(5, 60, 5))
ax.set_yticklabels(["5","10","15","20","25","30","...","65","70","75"]) 
ax.legend(('ClassificationAccuracy','One-Error','HammingLoss'),loc='upper right')
pylab.show()

此代码创建以下图形。enter image description here

答案 1 :(得分:0)

您可以从第二个函数的x值中减去40,以使x值的范围连续。这将为您提供0%至70%的范围。然后你可以按如下方式设置x轴的抽搐和实验:

x_ticks = range(71, 0, 10)
a.set_xticks(x_ticks)
a.set_xticklabels([str(x) for x in [0, 10, 20, 30, 70, 80, 90, 100]])

a是当前轴。所以基本上,你将函数绘制在0%到70%的范围内,但是用一个间隙标记轴。

举例说明 - 以下脚本:

from numpy import arange
import matplotlib.pyplot as plt

x1 = arange(0, 26) # first function
y1 = x1**2

x2 = arange(75, 100) # second function
y2 = x2*4 + 10

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(x1, y1)
ax.plot(x2 - 40, y2) # shift second function 40 to left
ax.set_xticks(range(0, 61, 5)) # set custom x-ticks
# set labels for x-ticks - labels have the gap we want
ax.set_xticklabels([str(x) for x in range(0, 26, 5) + range(70, 101, 5)])
plt.show()

生成以下图表(请注意x标签):

Output of script above

答案 2 :(得分:0)

matplotlib 文档实际上有 an example 如何做到这一点。

基本思想是将绘图分成两个子图,在每个图上放置相同的图,然后更改每个图的轴以仅显示特定部分,然后使其看起来更好。

所以,让我们应用它。想象一下这是您的起始代码:

import matplotlib.pyplot as plt
import random, math

# Generates data
i = range(10)
x = [math.floor(random.random() * 5) + 67 for i in range(10)]
y = [math.floor(random.random() * 5) + 22 for i in range(10)]
z = [math.floor(random.random() * 5) + 13 for i in range(10)]

# Original plot
fig, ax = plt.subplots()
ax.plot(i, x, 'ro-')
ax.plot(i, y, 'go-')
ax.plot(i, z, 'bo-')

plt.show()

Starting point

我们努力让x与其他部分分开。

首先,我们要绘制同一个图形两次,一个在另一个之上。为此,绘图功能需要是通用的。现在它应该看起来像这样:

# Plotting function
def plot(ax):
    ax.plot(i, x, 'ro-')
    ax.plot(i, y, 'go-')
    ax.plot(i, z, 'bo-')

# Draw the graph on two subplots
fig, (ax1, ax2) = plt.subplots(2, 1)
plot(ax1)
plot(ax2)

Two subplots of the same graph

现在这看起来更糟,但我们可以更改每个轴的范围以专注于我们想要的。现在我只是选择我知道会捕获所有数据的简单范围,但我稍后会专注于使轴相等。

# Changes graph axes
ax1.set_ylim(65, 75) # Top graph
ax2.set_ylim(5, 30) # Bottom graph

Subplots with altered axes

这越来越接近我们正在寻找的东西。现在我们需要让它看起来更好一点:

# Hides the spines between the axes
ax1.spines.bottom.set_visible(False)
ax2.spines.top.set_visible(False)
ax1.xaxis.tick_top()
ax1.tick_params(labeltop=False)  # Don't put tick labels at the top
ax2.xaxis.tick_bottom()

# Adds slanted lines to axes
d = .5  # proportion of vertical to horizontal extent of the slanted line
kwargs = dict(
    marker=[(-1, -d), (1, d)],
    markersize=12,
    linestyle='none',
    color='k',
    mec='k',
    mew=1,
    clip_on=False
)
ax1.plot([0, 1], [0, 0], transform=ax1.transAxes, **kwargs)
ax2.plot([0, 1], [1, 1], transform=ax2.transAxes, **kwargs)

Broken lines

最后,让我们修复轴。在这里,您需要做一些数学运算并决定更多的布局。例如,也许我们想让顶部的图变小,因为底部的图有两条线。为此,我们需要更改子图的高度比例,如下所示:

# Draw the graph on two subplots
# Bottom graph is twice the size of the top one
fig, (ax1, ax2) = plt.subplots(2, 1, gridspec_kw={'height_ratios': [1, 2]})

Resized subplots

最后,让轴匹配是个好主意。在这种情况下,因为底部图像的大小是顶部图像的两倍,我们需要更改一个的轴来反映这一点。这次我选择修改最上面的。底部的图表覆盖了 25 的范围,这意味着顶部的图表应该覆盖了 12.5 的范围。

# Changes graph axes
ax1.set_ylim(60.5, 73) # Top graph
ax2.set_ylim(5, 30) # Bottom graph

Final graph

这对我来说已经足够了。如果您不希望刻度与虚线重叠,您可以更多地使用轴或刻度标签。

最终代码:

import matplotlib.pyplot as plt
import random, math

# Generates data
i = range(10)
x = [math.floor(random.random() * 5) + 67 for i in range(10)]
y = [math.floor(random.random() * 5) + 22 for i in range(10)]
z = [math.floor(random.random() * 5) + 13 for i in range(10)]

# Plotting function
def plot(ax):
    ax.plot(i, x, 'ro-')
    ax.plot(i, y, 'go-')
    ax.plot(i, z, 'bo-')

# Draw the graph on two subplots
# Bottom graph is twice the size of the top one
fig, (ax1, ax2) = plt.subplots(2, 1, gridspec_kw={'height_ratios': [1, 2]})
plot(ax1)
plot(ax2)

# Changes graph axes
ax1.set_ylim(60.5, 73) # Top graph
ax2.set_ylim(5, 30) # Bottom graph

# Hides the spines between the axes
ax1.spines.bottom.set_visible(False)
ax2.spines.top.set_visible(False)
ax1.xaxis.tick_top()
ax1.tick_params(labeltop=False)  # Don't put tick labels at the top
ax2.xaxis.tick_bottom()

# Adds slanted lines to axes
d = .5  # proportion of vertical to horizontal extent of the slanted line
kwargs = dict(
    marker=[(-1, -d), (1, d)],
    markersize=12,
    linestyle='none',
    color='k',
    mec='k',
    mew=1,
    clip_on=False
)
ax1.plot([0, 1], [0, 0], transform=ax1.transAxes, **kwargs)
ax2.plot([0, 1], [1, 1], transform=ax2.transAxes, **kwargs)

plt.show()