pythonmatplotlib

How can I stop a matplotlib table overlapping a graph?


The MWE below produces a plot like this:

enter image description here

The row labels, X, Y, Z, overlap the right hand side of the bar chart in an ugly fashion. I'd like them moved further to the right, leaving a small margin between the chart and the table. The documentation for matplotlib.pyplot.table doesn't have any loc options that would allow this. The bbox argument might allow it, but it would seem to require trial and error with different bounding boxes to get that working.

Is there a way to lay this out more cleanly?

import matplotlib.pyplot as plt
import seaborn as sns

plt.figure(figsize=(9, 5), dpi=300)
ax = sns.barplot(
    x = range(1, 3),
    y = [15,30],
    legend=False,
)
plt.table(cellText=['A','B','C'], rowLabels=['X','Y','Z'], colWidths=[0.15], loc='right')
plt.show()

Solution

  • The trick is to split your figure into two axes instead of drawing the table on top of the bar-axes;make_axes_locatable(ax) + append_axes("right", size="20%", pad=0.2) carves out a narrow, padded strip on the right, axis("off") hides its ticks/spines, and ax_table.table(…) draws your table there so it never overlaps the bars.

    That's the best I could come up with:

    import matplotlib.pyplot as plt
    import seaborn as sns
    from mpl_toolkits.axes_grid1 import make_axes_locatable
    
    fig, ax = plt.subplots()
    sns.barplot(x=[1,2], y=[15,30], ax=ax)
    
    divider   = make_axes_locatable(ax)
    ax_table  = divider.append_axes("right", size="20%", pad=0.2)
    ax_table.axis("off")
    
    ax_table.table(
        cellText=[["A"],["B"],["C"]],
        rowLabels=["X","Y","Z"],
        loc="center"
    )
    
    plt.show()
    

    Output:

    enter image description here