matplotlib中条形图内的轴斜线标记是否损坏?

时间:2018-12-06 00:31:56

标签: python matplotlib bar-chart

我看过matplotlib示例,这些示例在轴上放置了折断的斜杠标记,例如this one

我的问题是,如何将其放置在横条断裂的地方?可以通过编程的方式来逐月更新时间序列图吗?

下面是使用Excel进行操作的示例。注意巴黎6月酒吧和马德里5月酒吧中的波浪号。波浪线隐藏了它所覆盖的栏的一部分。

broken axis excel example

我还提供了更简单的示例数据以及到目前为止我能做的事情。

XX = pd.Series([200,400,100,1400],index=['x1','x2','x3','x4'])
fig, (ax1,ax2) = plt.subplots(2,1,sharex=True,
                         figsize=(5,6))
ax1.spines['bottom'].set_visible(False)
ax1.tick_params(axis='x',which='both',bottom=False)
ax2.spines['top'].set_visible(False)
ax2.set_ylim(0,500)
ax1.set_ylim(1200,1500)
ax1.set_yticks(np.arange(1000,1501,100))
XX.plot(ax=ax1,kind='bar')
XX.plot(ax=ax2,kind='bar')
for tick in ax2.get_xticklabels():
    tick.set_rotation(0)
d = .015  
kwargs = dict(transform=ax1.transAxes, color='k', clip_on=False)
ax1.plot((-d, +d), (-d, +d), **kwargs)      
ax1.plot((1 - d, 1 + d), (-d, +d), **kwargs)
kwargs.update(transform=ax2.transAxes)  
ax2.plot((-d, +d), (1 - d, 1 + d), **kwargs)  
ax2.plot((1 - d, 1 + d), (1 - d, 1 + d), **kwargs)
plt.show()

enter image description here

2 个答案:

答案 0 :(得分:2)

前段时间我需要断开y轴并创建一些代码来做到这一点。现在,我已将其提交给PyPi,以便其他人可以使用它。不过,它远非最终版本。欢迎任何评论,当然还有GitHub project,任何人都可以在其中进行协作。任何问题,代码和其他任何东西都欢迎。

另外,请考虑阅读以下文章。在决定是否使用y轴之前,有一些很好的理由说明为什么可能不希望使用y轴损坏。我认为要点之一是,打破y轴会使比例感完全消失。由于它在有限的y轴范围内发生,因此看到这样的图可能会造成混乱。也就是说,如果使用的话,我建议观众了解使用这种情节可能产生的奇怪比例。

安装:

pip install plotinpy

以下是y轴折断的一些用法:

示例

简单的断线

plt.figure()
pnp.plot_bars_with_breaks(
    [1, 2, 30],
    [(15, 25)]
    )
plt.savefig("img/example1.png")

Example 1

样式断条

plt.figure()
pnp.plot_bars_with_breaks(
    [1, 2, 30, 1000],
    [(15, 25), (50, 975)],
    style="~~",
    break_args={"hatch": '///'}
    )
plt.savefig("img/example2.png")

Example 2

答案 1 :(得分:1)

为说明原理,您可以在钢筋超过下轴上限的位置以及钢筋超过上轴下限的每个位置放置相同类型的线。

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

XX = pd.Series([200,400,100,1400],index=['x1','x2','x3','x4'])
fig, (ax1,ax2) = plt.subplots(2,1,sharex=True,
                         figsize=(5,6))
ax1.spines['bottom'].set_visible(False)
ax1.tick_params(axis='x',which='both',bottom=False)
ax2.spines['top'].set_visible(False)

bs = 500
ts = 1000

ax2.set_ylim(0,bs)
ax1.set_ylim(ts,1500)
ax1.set_yticks(np.arange(1000,1501,100))

bars1 = ax1.bar(XX.index, XX.values)
bars2 = ax2.bar(XX.index, XX.values)

for tick in ax2.get_xticklabels():
    tick.set_rotation(0)
d = .015  
kwargs = dict(transform=ax1.transAxes, color='k', clip_on=False)
ax1.plot((-d, +d), (-d, +d), **kwargs)      
ax1.plot((1 - d, 1 + d), (-d, +d), **kwargs)
kwargs.update(transform=ax2.transAxes)  
ax2.plot((-d, +d), (1 - d, 1 + d), **kwargs)  
ax2.plot((1 - d, 1 + d), (1 - d, 1 + d), **kwargs)

for b1, b2 in zip(bars1, bars2):
    posx = b2.get_x() + b2.get_width()/2.
    if b2.get_height() > bs:
        ax2.plot((posx-3*d, posx+3*d), (1 - d, 1 + d), color='k', clip_on=False,
                 transform=ax2.get_xaxis_transform())
    if b1.get_height() > ts:
        ax1.plot((posx-3*d, posx+3*d), (- d, + d), color='k', clip_on=False,
                 transform=ax1.get_xaxis_transform())
plt.show()

enter image description here

它看起来不太好,但是当然可以采用更好的形状。

相关问题