5 Best Ways to Plot Two Horizontal Bar Charts Sharing the Same Y-Axis in Python Matplotlib

πŸ’‘ Problem Formulation: When working with data visualization in Python, a common task is to compare different datasets side by side. One effective way to accomplish this is by plotting two horizontal bar charts that share the same y-axis using Matplotlib. This article demonstrates five methods to plot such charts, making comparisons more intuitive and visually appealing. For instance, you may wish to compare the performance of two athletes across various disciplines, expecting two aligned bar charts with discipline labels on y-axis shared between them.

Method 1: Using Subplots

An efficient way to create two horizontal bar charts sharing the same y-axis is by using the subplots() function in Matplotlib to instantiate two axes objects. The subplots are placed next to each other, with only one displaying y-axis labels to avoid redundancy and maximize readability. This method is modular and easily customizable.

Here’s an example:

import matplotlib.pyplot as plt

# Sample data
categories = ['Category A', 'Category B', 'Category C']
values1 = [5, 10, 15]
values2 = [3, 12, 8]

fig, (ax1, ax2) = plt.subplots(1, 2, sharey=True)

# Plot on first axes
ax1.barh(categories, values1, color='skyblue')
ax1.set(title='Dataset 1')

# Plot on second axes
ax2.barh(categories, values2, color='lightgreen')
ax2.set(title='Dataset 2')

plt.tight_layout()
plt.show()

This code generates two horizontal bar charts placed side by side, sharing the same y-axis.

The subplots() function initializes two subplot axes objects, ax1 and ax2. The sharey=True parameter ensures that they share the same y-axis. We then plot the two datasets onto their respective axes using barh() for horizontal bars and assign different colors for visual distinction. The tight_layout() function is used to ensure that the plot is neatly arranged without any overlap.

Method 2: Using Twinx

The twinx() method is a powerful feature in Matplotlib that allows for a shared y-axis between two plots while enabling them to have independent x-axes. This is particularly useful when the range of values for the datasets is different but should be compared against the same categories.

Here’s an example:

import matplotlib.pyplot as plt

# Sample data
categories = ['Category A', 'Category B', 'Category C']
values1 = [5, 10, 15]
values2 = [3, 12, 8]

fig, ax1 = plt.subplots()

# Plot on first axes
ax1.barh(categories, values1, color='skyblue')
ax1.set_xlabel('Values for Dataset 1')

# Create a second x-axis for the second dataset
ax2 = ax1.twinx()
ax2.barh(categories, values2, color='lightcoral', alpha=0.6)
ax2.set_xlabel('Values for Dataset 2')

plt.show()

This code creates two overlaid horizontal bar charts sharing the same y-axis, with separate x-axes.

The use of twinx() creates a new axes object (ax2) that shares the y-axis with the original axes (ax1). Different colors and an alpha parameter are used to distinguish the datasets while allowing them to overlay. This method is useful when the datasets have different value ranges that require individual x-axis scaling.

Method 3: Inset Axes

Inset axes are a unique feature that allows a secondary chart to be embedded within a primary chart. By utilizing the inset_axes() from the mpl_toolkits.axes_grid1, we can create a clear and compact representation of two related datasets sharing the same categories.

Here’s an example:

from mpl_toolkits.axes_grid1 import inset_locator
import matplotlib.pyplot as plt

# Sample data
categories = ['Category A', 'Category B', 'Category C']
values1 = [5, 10, 15]
values2 = [3, 12, 8]

fig, ax1 = plt.subplots()

# Primary horizontal bar chart
ax1.barh(categories, values1, color='skyblue')

# Create an inset of the second bar chart
ax2 = inset_locator.inset_axes(ax1, width="30%", height="100%", loc='center right', borderpad=3)
ax2.barh(categories, values2, color='lightcoral', alpha=0.6)

plt.show()

This code snippet generates a horizontal bar chart with an inset chart on the right side, sharing the same y-axis.

With this approach, the inset_axes() method is used to create a smaller secondary axes (ax2) within the primary axes (ax1). We then plot the second dataset on this inset axis. The positioning and size of the inset can be controlled with the width, height, loc, and borderpad parameters.

Method 4: Using GridSpec

GridSpec is a flexible way to layout multiple plots within a figure. It allows plots to span multiple rows or columns, offering fine-grained control over the placement of subplots. When two horizontal bar charts need to be aligned with a shared y-axis, GridSpec can provide a tailored layout.

Here’s an example:

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

# Sample data
categories = ['Category A', 'Category B', 'Category C']
values1 = [5, 10, 15]
values2 = [3, 12, 8]

fig = plt.figure()
gs = gridspec.GridSpec(1, 2, width_ratios=[1, 1])

ax1 = fig.add_subplot(gs[0])
ax2 = fig.add_subplot(gs[1], sharey=ax1)

# Prevent y-axis labels from being on both plots
ax2.tick_params(labelleft=False)

# Plot the horizontal bar charts
ax1.barh(categories, values1, color='skyblue')
ax2.barh(categories, values2, color='lightgreen')

plt.tight_layout()
plt.show()

This code creates two aligned horizontal bar charts with shared y-axis using GridSpec to allocate space.

Here we define a GridSpec with one row and two columns with equal width ratios. We then create two subplot axes with shared y-axis by specifying the sharey parameter. The tick_params() method on ax2 ensures that y-axis labels only appear on the first chart to maintain a clean look.

Bonus One-Liner Method 5: Using Pandas

For those using Pandas for data handling, the library offers a one-liner solution to plot horizontal bar charts with a shared y-axis. It utilizes Matplotlib under the hood and provides a high-level interface for plotting.

Here’s an example:

import pandas as pd

# Sample data in a DataFrame
df = pd.DataFrame({
    'Category': ['Category A', 'Category B', 'Category C'],
    'Dataset 1': [5, 10, 15],
    'Dataset 2': [3, 12, 8]
}).set_index('Category')

# Plot using Pandas' plotting interface
ax = df.plot.barh(stacked=True, colormap='coolwarm')

plt.show()

This code utilizes Pandas’ data processing strength to plot two stacked horizontal bar charts with minimal code.

After constructing a Pandas DataFrame and setting the categories as the index, we call the plot.barh() method on the DataFrame. The stacked=True parameter indicates that we want our bars stacked horizontally, and the colormap provides color differentiation. While this approach does stack the data within the same bar, it might be a preferred visualization when you want to show cumulative information.

Summary/Discussion

  • Method 1: Using Subplots. Offers modular plotting and neat arrangement with tight_layout(). Does not readily support vastly different x-axis scales.
  • Method 2: Using Twinx. Effective for comparing different value ranges with separate x-axes. The overlay may reduce readability if not styled carefully.
  • Method 3: Inset Axes. Excellent for compact presentations. Insets may become hard to read if too many categories or small sizes are involved.
  • Method 4: Using GridSpec. Provides granular control over subplot placement. May require additional tweaking to get the spacing right.
  • Bonus Method 5: Using Pandas. Simple one-liner for quick plots. The stacked bars may not be suitable for all comparisons as they show cumulative data.