pandas 调整gridspec子图以与间距对齐

lf3rwulv  于 2023-03-28  发布在  其他
关注(0)|答案(2)|浏览(164)

我使用matplotlib.gridspec为3个轴创建一个网格。
我现在的代码看起来像:

from matplotlib import pyplot as plt
from matplotlib.gridspec import GridSpec
import pandas as pd

df = pd.DataFrame({'d1': [20,30,40], 'd2': [10,20,30]}, index=['a', 'b', 'c']) #  Dataset to emulate real data structure
df = df.apply(lambda l: l / l.sum() * 100).T
df.index = ['Some dataset', 'Some dataset 2']

fig = plt.figure(figsize=(6.25, 4.0))
gs = GridSpec(3, 2, figure=fig)

ax1 = fig.add_subplot(gs[:2, 0])
ax2 = fig.add_subplot(gs[:2, 1])
hbar_ax = fig.add_subplot(gs[2, :])

df.plot(ax=hbar_ax, kind='barh', stacked=True, width=0.5, color=['#FF3B3B', '#F4B083', '#9CD5A4'], legend=None)
hbar_ax.invert_yaxis()
hbar_ax.set_xlim(-1, 101)

for n in df:
    for i, (cs, ab, pc) in enumerate(zip(df.iloc[:, 0:].cumsum(1)[n], 
                                         df[n], df[n])):
        hbar_ax.text(cs - ab / 2, i, str(np.round(pc, 1)) + '%', 
                 va = 'center', ha = 'center', fontsize='medium')

hbar_ax.tick_params(axis='both', which='both', length=0)
hbar_ax.tick_params(
    axis='x',
    which='both',
    bottom=False,
    top=False,
    labelbottom=False)

plt.tight_layout()

得出以下结果:

但我不知道如何调整顶部的图空间看起来像这样:

r6vfmomb

r6vfmomb1#

您可以使用subfigures,例如:

import numpy as np
from matplotlib import pyplot as plt
from matplotlib.gridspec import GridSpec
import pandas as pd

df = pd.DataFrame({'d1': [20,30,40], 'd2': [10,20,30]}, index=['a', 'b', 'c']) #  Dataset to emulate real data structure
df = df.apply(lambda l: l / l.sum() * 100).T
df.index = ['Some dataset', 'Some dataset 2']

# create subplot grid (using wpace to set space between top two plots)
fig, axs = plt.subplots(3, 2, layout="constrained", figsize=(6.25, 4.0), gridspec_kw={"wspace": 0.2})
gridspec = axs[0, 0].get_subplotspec().get_gridspec()

# add in top two plots (first removing existing axes)
for ax in axs[:2, 0]:
    ax.remove()
for ax in axs[:2, 1]:
    ax.remove()
ax1 = fig.add_subplot(gridspec[:2, 0])
ax2 = fig.add_subplot(gridspec[:2, 1])

# create subfigure for bottom plot
for ax in axs[2, :]:
    ax.remove()

subfig = fig.add_subfigure(gridspec[2, :])

# bottom axis
hbar_ax = subfig.subplots(1)

df.plot(ax=hbar_ax, kind='barh', stacked=True, width=0.5, color=['#FF3B3B', '#F4B083', '#9CD5A4'], legend=None)
hbar_ax.invert_yaxis()
hbar_ax.set_xlim(-1, 101)

for n in df:
    for i, (cs, ab, pc) in enumerate(zip(df.iloc[:, 0:].cumsum(1)[n],
                                         df[n], df[n])):
        hbar_ax.text(cs - ab / 2, i, str(np.round(pc, 1)) + '%',
                 va = 'center', ha = 'center', fontsize='medium')

hbar_ax.tick_params(axis='both', which='both', length=0)
hbar_ax.tick_params(
    axis='x',
    which='both',
    bottom=False,
    top=False,
    labelbottom=False)

fig.show()

这给出:

kcugc4gi

kcugc4gi2#

@Matt_Pitkin的答案是正确的,子图绝对是实现这一点的最佳方法。然而,更惯用的是:

import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl

import pandas as pd

df = pd.DataFrame({'d1': [20,30,40], 'd2': [10,20,30]}, index=['a', 'b', 'c'])
df = df.apply(lambda l: l / l.sum() * 100).T
df.index = ['Some dataset', 'Some dataset 2']

fig = plt.figure(layout='constrained', figsize=(6.25, 4.0))
subfigs = fig.subfigures(nrows=2, ncols=1, height_ratios=[1, 0.5])

axs = subfigs[0].subplots(1, 2, gridspec_kw={"wspace": 0.2})

hbar_ax  = subfigs[1].subplots()

df.plot(ax=hbar_ax, kind='barh', stacked=True, width=0.5, color=['#FF3B3B', '#F4B083', '#9CD5A4'], legend=None)
hbar_ax.invert_yaxis()
hbar_ax.set_xlim(-1, 101)

相关问题