简体   繁体   English

如何在 matplotlib 中移动轴标签、移动子图和修改轴缩放

[英]How to shift axis labels, shift subplots and modify axis scaling in matplotlib

I am trying to make a plot like this我正在尝试像这样制作 plot

在此处输入图像描述

using matplotlib.使用 matplotlib。

Currently I have this plot:目前我有这个 plot:

在此处输入图像描述

which was generated using this code:这是使用此代码生成的:

import matplotlib.pyplot as plt
import matplotlib as mpl
import pandas as pd

width = 0.4
mpl.rcParams.update({'font.size':15})
mpl.rcParams.update({'legend.columnspacing':0.5})

##############################################################
# BEGIN: Prepare data                                        #
##############################################################
energy_cm = 1550835.86856494
energy_fm = 1456129.29966378
energy_cm_trad = 1393026.50949191
energy_fm_trad = 1314814.95236864
energy_cm_hw = 1200000
energy_fm_hw = 1100000

data_energy = { 'Algorithm' : ['Algorithm 1', 'Algorithm 2'],
       'SW' : [energy_cm, energy_fm],
       'HW' : [energy_cm_hw, energy_fm_hw],
       'Trad' : [energy_cm_trad, energy_fm_trad]
    }

df_energy = pd.DataFrame(data_energy)

##############################################################
# END: Prepare data                                          #
##############################################################

##############################################################
# BEGIN: Split the bars into two halves                      #
##############################################################
fig, (ax, ax2) = plt.subplots(2, 1, sharex=True)

df_energy[['Algorithm', 'SW', 'Trad',
           'HW']].set_index('Algorithm').plot(kind='bar', legend=True,
                                              width=width, rot=0,
                                              ax=ax,
                                              color=('sandybrown','rosybrown',
                                                     'goldenrod','indianred','tomato','r'))

df_energy[['Algorithm', 'SW', 'Trad',
           'HW']].set_index('Algorithm').plot(kind='bar',
                                              legend=False,
                                              width=width, rot=0,
                                              ax=ax2,
                                              color=('sandybrown','rosybrown',
                                                     'goldenrod','indianred','tomato','r'))

max_lengths = sorted(df_energy.max(axis=0).values[1:])
min_lengths = sorted(df_energy.min(axis=0).values[1:])

# zoom-in / limit the view to different portions of the data
ax.set_ylim(max_lengths[-2] * 0.8, max_lengths[-1] * 1.1)  # outliers only
ax2.set_ylim(0, min_lengths[0] * 1.1)  # most of the data

# hide the spines between ax and ax2
ax.spines['bottom'].set_visible(False)
ax2.spines['top'].set_visible(False)
ax.xaxis.tick_top()
ax.tick_params(labeltop='off')  # don't put tick labels at the top
ax2.xaxis.tick_bottom()

d = .01  # how big to make the diagonal lines in axes coordinates
# arguments to pass to plot, just so we don't keep repeating them
kwargs = dict(transform=ax.transAxes, color='k', clip_on=False)
ax.plot((-d, +d), (-d, +d), **kwargs)        # top-left diagonal
ax.plot((1 - d, 1 + d), (-d, +d), **kwargs)  # top-right diagonal

kwargs.update(transform=ax2.transAxes)  # switch to the bottom axes
ax2.plot((-d, +d), (1 - d, 1 + d), **kwargs)  # bottom-left diagonal
ax2.plot((1 - d, 1 + d), (1 - d, 1 + d), **kwargs)  # bottom-right diagonal

##############################################################
# END: Split the bars into two halves                        #
##############################################################

##############################################################
# BEGIN: Labels                                              #
##############################################################
# Remove X lables from the upper half of the plot
ax.tick_params(
    axis='x',          # changes apply to the x-axis
    which='both',      # both major and minor ticks are affected
    bottom=False,      # ticks along the bottom edge are off
    top=False,         # ticks along the top edge are off
    labeltop=False,
    labelbottom=False) # labels along the bottom edge are off

ax.set_ylabel('Energy in nJ')
ax.set_xlabel("")
ax2.set_xlabel("")

##############################################################
# END: Labels                                                #
##############################################################

##############################################################
# BEGIN: Scaling                                             #
##############################################################
mf = mpl.ticker.ScalarFormatter(useMathText=True)
mf.set_powerlimits((-2,2))
ax.yaxis.set_major_formatter(mf)
ax2.yaxis.set_major_formatter(mf)

##############################################################
# END: Scaling                                               #
##############################################################

fig.tight_layout()
plt.show()

I am following matplotlibsexample code for the broken axis and I am using code from the answer to my previous question in order to scale the numbers on the y-axis.我正在关注断轴的 matplotlibs示例代码,并且我正在使用上一个问题的答案中的代码来缩放 y 轴上的数字。

I would like to:我想:

  • Remove the scaling label from the lower subplot从下部子图中删除缩放 label
  • Reduce the distance between the upper and the lower sublot缩小上下子批次之间的距离
  • Shift the y-label down so that it applies to both the upper and the lower subplots向下移动 y 标签,使其适用于上子图和下子图

Thus the result would look like the fist image in this question.因此,结果看起来就像这个问题中的第一个图像。

How can I achieve these three things?我怎样才能实现这三件事? Any help is appreciated, even if it doesn't solve all three problems...任何帮助表示赞赏,即使它不能解决所有三个问题......

  • use fig.subplots_adjust() to change the spacing between the two axes.使用fig.subplots_adjust()更改两个轴之间的间距。
  • I replaced the ylabel with fig.text() to center the label vertically in the figure我用fig.text()替换了ylabel以使 label 在图中垂直居中
  • use ax2.yaxis.get_offset_text().set_visible(False) to hide the exponent on the bottom axis.使用ax2.yaxis.get_offset_text().set_visible(False)隐藏底轴上的指数。

Note that the limits of your axes are poorly chosen as the top of the HW bar in the "Count Min" category is visible in both the bottom and top axes.请注意,您的轴的限制选择不当,因为“计数最小值”类别中的硬件栏顶部在底部和顶部轴中都可见。

complete code:完整代码:

import matplotlib.pyplot as plt
import matplotlib as mpl
import pandas as pd

width = 0.4
mpl.rcParams.update({'font.size':15})
mpl.rcParams.update({'legend.columnspacing':0.5})


# BEGIN: Prepare data 
energy_cm = 1550835.86856494
energy_fm = 1456129.29966378
energy_cm_trad = 1393026.50949191
energy_fm_trad = 1314814.95236864
energy_cm_hw = 1200000
energy_fm_hw = 1100000

data_energy = { 'Algorithm' : ['Algorithm 1', 'Algorithm 2'],
       'SW' : [energy_cm, energy_fm],
       'HW' : [energy_cm_hw, energy_fm_hw],
       'Trad' : [energy_cm_trad, energy_fm_trad]
    }

df_energy = pd.DataFrame(data_energy)


# BEGIN: Split the bars into two halves
fig, (ax, ax2) = plt.subplots(2, 1, sharex=True)
kw = dict(width=width, rot=0,
          color=('sandybrown','rosybrown','goldenrod','indianred','tomato','r'))
df_energy[['Algorithm', 'SW', 'Trad',
           'HW']].set_index('Algorithm').plot(kind='bar', legend=True, ax=ax, **kw)

df_energy[['Algorithm', 'SW', 'Trad',
           'HW']].set_index('Algorithm').plot(kind='bar', legend=False, ax=ax2, **kw)

max_lengths = sorted(df_energy.max(axis=0).values[1:])
min_lengths = sorted(df_energy.min(axis=0).values[1:])

# zoom-in / limit the view to different portions of the data
ax.set_ylim(max_lengths[-2] * 0.8, max_lengths[-1] * 1.1)  # outliers only
ax2.set_ylim(0, min_lengths[0] * 1.1)  # most of the data

# hide the spines between ax and ax2
ax.spines['bottom'].set_visible(False)
ax2.spines['top'].set_visible(False)
ax.xaxis.tick_top()
ax.tick_params(labeltop='off')  # don't put tick labels at the top
ax2.xaxis.tick_bottom()

d = .01  # how big to make the diagonal lines in axes coordinates
# arguments to pass to plot, just so we don't keep repeating them
kwargs = dict(transform=ax.transAxes, color='k', clip_on=False)
ax.plot((-d, +d), (-d, +d), **kwargs)        # top-left diagonal
ax.plot((1 - d, 1 + d), (-d, +d), **kwargs)  # top-right diagonal

kwargs.update(transform=ax2.transAxes)  # switch to the bottom axes
ax2.plot((-d, +d), (1 - d, 1 + d), **kwargs)  # bottom-left diagonal
ax2.plot((1 - d, 1 + d), (1 - d, 1 + d), **kwargs)  # bottom-right diagonal



# BEGIN: Labels
# Remove X lables from the upper half of the plot
ax.tick_params(
    axis='x',          # changes apply to the x-axis
    which='both',      # both major and minor ticks are affected
    bottom=False,      # ticks along the bottom edge are off
    top=False,         # ticks along the top edge are off
    labeltop=False,
    labelbottom=False) # labels along the bottom edge are off

fig.text(0,0.5,'Energy in nJ', rotation=90, va='center', ha='left')
ax.set_xlabel("")
ax2.set_xlabel("")


# BEGIN: Scaling
ax.ticklabel_format(style='sci', axis='y', useOffset=True, scilimits=(0,0))
ax2.ticklabel_format(style='sci', axis='y', useOffset=True, scilimits=(0,0))
ax2.yaxis.get_offset_text().set_visible(False)


fig.tight_layout()
fig.subplots_adjust(hspace=0.05)
plt.show()

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM