Controlling the width of bars in Matplotlib with per-month data

To control the width of bars in Matplotlib with per-month data, you can dynamically calculate bar widths based on the actual time intervals between dates. This ensures consistent visual representation regardless of varying month lengths.

Steps to Control Bar Width

  • Set the figure size and adjust the padding between and around the subplots
  • Create a list of datetime objects representing monthly data points
  • Calculate bar widths based on the actual days between consecutive months
  • Plot the bar chart with calculated widths using plt.bar()
  • Display the figure using show() method

Example

Here's how to create a bar chart with per-month data and controlled bar widths ?

import numpy as np
import datetime
from matplotlib import pyplot as plt

plt.rcParams["figure.figsize"] = [7.50, 3.50]
plt.rcParams["figure.autolayout"] = True

# Create monthly datetime objects
dates = [datetime.datetime(2021, 1, 1, 0, 0),
         datetime.datetime(2021, 2, 1, 0, 0),
         datetime.datetime(2021, 3, 1, 0, 0)]

# Sample data values
values = np.cos(np.arange(3) * 2)

# Calculate bar widths based on actual days between months
widths = [(dates[j+1]-dates[j]).days for j in range(len(dates)-1)] + [30]

plt.bar(dates, values, width=widths)
plt.title('Monthly Data with Controlled Bar Width')
plt.xlabel('Months')
plt.ylabel('Values')

plt.show()

How It Works

The key part is calculating the width parameter:

import datetime

# Example dates
dates = [datetime.datetime(2021, 1, 1),
         datetime.datetime(2021, 2, 1),
         datetime.datetime(2021, 3, 1)]

# Calculate differences in days
widths = [(dates[j+1]-dates[j]).days for j in range(len(dates)-1)] + [30]
print("Bar widths in days:", widths)
Bar widths in days: [31, 28, 30]

Extended Example with More Months

Here's a more comprehensive example with a full year of data ?

import numpy as np
import datetime
from matplotlib import pyplot as plt

# Create a full year of monthly data
months = []
for month in range(1, 13):
    months.append(datetime.datetime(2021, month, 1))

# Generate sample sales data
sales_data = np.random.randint(100, 500, 12)

# Calculate widths for each month
widths = []
for i in range(len(months)-1):
    width = (months[i+1] - months[i]).days
    widths.append(width)
widths.append(31)  # December width

plt.figure(figsize=(12, 6))
plt.bar(months, sales_data, width=widths, alpha=0.7, color='skyblue')
plt.title('Monthly Sales Data with Proportional Bar Widths')
plt.xlabel('Month')
plt.ylabel('Sales')
plt.xticks(rotation=45)
plt.tight_layout()

plt.show()

Key Points

  • Width calculation: Use (date2 - date1).days to get the actual number of days between months
  • Last bar: Add a manual width for the final bar since there's no next date to calculate from
  • Proportional representation: Bars will be wider for months with more days (31 days) and narrower for February (28/29 days)
  • Visual consistency: This approach ensures the chart accurately represents time intervals

Conclusion

By calculating bar widths based on actual days between months, you create more accurate time-based visualizations. This method ensures that longer months appear proportionally wider than shorter months, providing a true representation of temporal data.

Updated on: 2026-03-25T21:36:55+05:30

707 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements