In my years of building data dashboards for US-based financial firms, I’ve realized that Matplotlib’s default scaling isn’t always perfect.
Sometimes, the auto-scaling feature hides the small differences between data points that actually matter for your analysis.
In this tutorial, I will show you exactly how to take control of your Y-axis limits to make your bar charts more readable and professional.
Why You Need to Manually Set the Y-Axis Range
By default, Matplotlib tries to be helpful by fitting all your data into the frame.
However, if you are comparing the GDP of different US states or looking at annual inflation rates, you might want a specific starting point.
Starting your Y-axis at a value other than zero can sometimes highlight trends, but you must be careful not to mislead your audience.
I personally use custom ranges when I need to zoom in on specific fluctuations or when I need multiple charts to share the same scale for a fair comparison.
Method 1: Use the plt.ylim() Function
The simple way to set the Y-axis range is by using the plt.ylim() function. This is part of the functional interface of Matplotlib.
I find this method incredibly useful when I am writing quick scripts or doing exploratory data analysis.
In the example below, I’ll plot the average monthly rent prices in major US cities. Without setting the limit, the differences might look negligible.
import matplotlib.pyplot as plt
# Data: Average Monthly Rent in USD for 2023
cities = ['New York', 'San Francisco', 'Miami', 'Chicago', 'Austin']
rent_prices = [3700, 3500, 2800, 2200, 2100]
# Creating the bar chart
plt.bar(cities, rent_prices, color='skyblue')
# Setting the Y-axis range (Lower limit, Upper limit)
# I want to start at 2000 to emphasize the differences above the baseline
plt.ylim(1500, 4000)
# Adding labels and title
plt.xlabel('US Cities')
plt.ylabel('Average Rent ($)')
plt.title('Average Monthly Rent Comparison (Selected US Cities)')
# Display the plot
plt.show()You can see the output in the screenshot below.

When you run this, you’ll notice how the bars start from the 1500 mark. This “zooms in” on the differences between the cities.
Method 2: Use the set_ylim() Method (Object-Oriented Approach)
As I progressed in my career, I moved away from simple scripts to the object-oriented approach. It offers much more control.
Using axes.set_ylim() is the professional way to handle plots, especially when you are working with subplots (multiple charts in one figure).
Let’s look at an example involving the median household income in different US regions.
import matplotlib.pyplot as plt
# Data: Median Household Income (Hypothetical US Regional Data)
regions = ['Northeast', 'Midwest', 'South', 'West']
income = [77000, 68000, 62000, 75000]
# Create figure and axes
fig, ax = plt.subplots(figsize=(8, 6))
# Plotting the data
ax.bar(regions, income, color='darkgreen')
# Setting the Y-axis range using the object-oriented method
ax.set_ylim(0, 90000)
# Customizing the chart
ax.set_xlabel('US Region')
ax.set_ylabel('Annual Income (USD)')
ax.set_title('Median Household Income by Region')
# Show plot
plt.tight_layout()
plt.show()You can see the output in the screenshot below.

In this case, I set the upper limit to 90,000 to provide some “breathing room” at the top of the chart for data labels or annotations.
Method 3: Dynamically Setting Limits Based on Data
In many of my real-world projects, the data changes every day. Hardcoding numbers like 4000 or 90000 isn’t always practical.
I often calculate the limits dynamically based on the maximum and minimum values in my dataset.
This ensures that my charts always look perfectly framed, regardless of the values coming from the database.
Here is how I handle dynamic scaling using US Tech Company stock prices as an example.
import matplotlib.pyplot as plt
# Data: Stock Prices of US Tech Giants (Sample values)
companies = ['Apple', 'Microsoft', 'Alphabet', 'Amazon', 'Meta']
prices = [185, 405, 145, 175, 480]
# Calculate dynamic limits
buffer = 0.15 # 15% padding
ymin = min(prices) * (1 - buffer)
ymax = max(prices) * (1 + buffer)
plt.figure(figsize=(10, 5))
plt.bar(companies, prices, color='teal')
# Apply dynamic limits
plt.ylim(ymin, ymax)
plt.xlabel('Company')
plt.ylabel('Price per Share (USD)')
plt.title('US Tech Stock Price Comparison (Dynamic Scaling)')
plt.show()You can see the output in the screenshot below.

By adding a buffer (15% in this case), I ensure the bars aren’t touching the top or bottom edges of the plot area.
Handle the Bottom Limit Only
Sometimes, you only care about where the Y-axis starts, and you want Matplotlib to figure out where it should end.
I often do this when I want to ensure the axis starts at zero (which is a best practice for bar charts), but I don’t know how high the data will go.
You can achieve this by passing None to the second argument of the limit functions.
import matplotlib.pyplot as plt
# Data: Voter Turnout in US Elections (Percentage)
years = ['2008', '2012', '2016', '2020']
turnout = [61.6, 58.6, 60.1, 66.7]
plt.bar(years, turnout, color='navy')
# Setting only the bottom limit to 0
plt.ylim(bottom=0)
plt.xlabel('Election Year')
plt.ylabel('Turnout Percentage (%)')
plt.title('US Presidential Election Voter Turnout')
plt.show()This keeps the data honest by showing the full length of the bars from zero, while letting the top end adjust to the 2020 peak.
Customize Y-Axis Ticks alongside Range
Setting the range is only half the battle. Often, I find that I also need to change the “ticks” (the numbers on the side) to match my new range.
If you set a range from 0 to 100, but the ticks are every 10 units, it might look cluttered.
I use np.arange or plt.yticks() to control exactly which numbers appear on my Y-axis.
import matplotlib.pyplot as plt
import numpy as np
# Data: Electric Vehicle (EV) Sales in the US (Thousands)
quarters = ['Q1', 'Q2', 'Q3', 'Q4']
sales = [250, 310, 290, 380]
plt.bar(quarters, sales, color='orange')
# Set Range
plt.ylim(0, 500)
# Set Ticks manually every 100 units
plt.yticks(np.arange(0, 501, 100))
plt.xlabel('2023 Quarters')
plt.ylabel('Units Sold (Thousands)')
plt.title('US EV Quarterly Sales Performance')
plt.show()This creates a very clean, professional-looking grid that is easy for stakeholders to read.
Common Issues to Avoid
When I was a beginner, I often made the mistake of setting the Y-limit too tight.
If your data point is exactly 100 and you set your limit to 100, the bar will touch the very top of the frame, which usually looks cramped.
Another trap is “truncating” the Y-axis. In the US, news outlets are often criticized for starting a bar chart at 50% to make a 2% difference look huge.
Always ask yourself if your chosen Y-axis range is providing a fair representation of the data.
I hope you find this guide useful when you’re working on your next Python data visualization project.
Setting the Y-axis range is a small change, but it makes a massive difference in how your charts are perceived.
You may also read:
- Adjust the X-Axis Limits in a Matplotlib Heatmap
- Set Matplotlib xlim for Datetime Objects in Python
- How to Update Matplotlib Scatter Plot in a Loop
- Set a Logarithmic Scale on the Y-Axis in Matplotlib

I am Bijay Kumar, a Microsoft MVP in SharePoint. Apart from SharePoint, I started working on Python, Machine learning, and artificial intelligence for the last 5 years. During this time I got expertise in various Python libraries also like Tkinter, Pandas, NumPy, Turtle, Django, Matplotlib, Tensorflow, Scipy, Scikit-Learn, etc… for various clients in the United States, Canada, the United Kingdom, Australia, New Zealand, etc. Check out my profile.