How do I define the range of the Y-Axis in MatPlotLib?

Question:

I have read countless posts on stackoverflow suggesting to use plt.ylim(low,high) to define the desired range.

I also tried plt.axis([x_low, x_high, y_low, y_high]). But it none of them work for me.

I am trying to plot voltage over time. I have 530 values that I want to plot, which I have stored in a list. The changes between the values are very little.

The data is in the range [4198, 4199]

I want to see a flat, horizontal line. Instead, I see a badly scaled plot where the line-graph ends up looking like a bar graph, highlighting the smallest changes, like this:

enter image description here

Here is the code that I have:

start = findStart(lines)
end = findEnd(lines, start)
q = enqueueVoltages(start, end)
x = range(len(q))
plt.plot(x, q)
#plt.axis([0,550,3000,4200])
plt.ylabel('Voltage (mV)')
plt.xlabel('Time (s)')
plt.show()

When I try it with the lines defining the desired axes ranges, I get this image:
enter image description here

For reference, here is the whole script I am running (with the function definitions):

def findStart(lines):
    count = 0
    for line in lines:
        count += 1
        if(line.rfind('***') > -1):
            start = count
            break
    
    return start

def findEnd(lines, start):
    count = 0
    for line in lines[start:]:
        count += 1
        if(line.rfind('***') > -1):
            end = count + start
            break
    
    return end

def enqueueVoltages(lines, start, end):
    q = []
    counter=0
    for i in range(start+1, end-1):
        beg = lines[i].find('tt')
        voltage = lines[i][beg+2:beg+6]
        counter += 1
        q.append(voltage)
        print(voltage)

    return q


f = open(data_path, 'r')
lines = f.readlines()

start = findStart(lines)
end = findEnd(lines, start)
q = enqueueVoltages(lines, start, end)
x = range(len(q))
plt.plot(x, q)
plt.ylim([3000,4200])
plt.gca().invert_yaxis()

plt.ylabel('Voltage (mV)')
plt.xlabel('Time (s)')
plt.show()


print("Starting:t{}nEnding:tt{}n".format(start, end))

f.close()

Here is the sample data I am processing (.txt file):

Start time: Wed Sep 14 15:05:14 2022        

***
Wed Sep 14 15:05:16 2022        4199
Wed Sep 14 15:05:17 2022        4199
Wed Sep 14 15:05:18 2022        4199
Wed Sep 14 15:05:20 2022        4199
Wed Sep 14 15:05:21 2022        4199
Wed Sep 14 15:05:22 2022        4199
Wed Sep 14 15:05:23 2022        4199
Wed Sep 14 15:05:24 2022        4199
Wed Sep 14 15:05:25 2022        4199
Wed Sep 14 15:05:26 2022        4199
Wed Sep 14 15:05:27 2022        4199
Wed Sep 14 15:05:29 2022        4199
Wed Sep 14 15:05:30 2022        4199
Wed Sep 14 15:05:31 2022        4199
Wed Sep 14 15:05:32 2022        4199
Wed Sep 14 15:05:33 2022        4199
Wed Sep 14 15:05:34 2022        4199
Wed Sep 14 15:05:35 2022        4199
Wed Sep 14 15:05:36 2022        4199
Wed Sep 14 15:05:38 2022        4199
Wed Sep 14 15:05:39 2022        4199
Wed Sep 14 15:05:40 2022        4199
Wed Sep 14 15:05:41 2022        4199
Wed Sep 14 15:05:42 2022        4199
Wed Sep 14 15:05:43 2022        4199
Wed Sep 14 15:05:44 2022        4199
Wed Sep 14 15:05:46 2022        4199
Wed Sep 14 15:05:47 2022        4199
Wed Sep 14 15:05:48 2022        4199
Wed Sep 14 15:05:49 2022        4199
Wed Sep 14 15:05:50 2022        4199
Wed Sep 14 15:05:51 2022        4199
Wed Sep 14 15:05:52 2022        4199
Wed Sep 14 15:05:53 2022        4199
Wed Sep 14 15:05:55 2022        4199
Wed Sep 14 15:05:56 2022        4199
Wed Sep 14 15:05:57 2022        4199
Wed Sep 14 15:05:58 2022        4199
Wed Sep 14 15:05:59 2022        4199

Thanks in advance for looking into it.

Asked By: Harit Krishan

||

Answers:

You need to provide the limits as tuple or list:

plt.ylim([y_low, y_high])
# or
plt.ylim((y_low, y_high))
Answered By: Flow
import matplotlib.pyplot as plt                                                                          
import numpy as np                                                                                       
                                                                                                        
# This emulates data like yours.                                                                                     
t = np.linspace(0, 550, 50)                                                                              
sample = np.random.uniform(low=4198, high=4199, size=(50,))                                              
                                                                                                        
plt.plot(t, sample)                                                                                    
plt.ylim(4100, 4300) # This DOES produce the effect that you want!!
plt.ylabel('Voltage (mV)')
plt.xlabel('Time (s)')                                
plt.show()

The issue must come from how you pack your data into the two lists that you plot.

According to your whole script, the problem comes from how you process your data. In particular, the return statements of findStart and findEnd make references to a local variable that is NOT referenced unless the if statement returns true. This throws an error using Python 3.8 and 3.10 (I didn’t try others)

Like others suspected, I’d suggest you to debug these functions in order to make sure they do what you want. In any case, there is nothing wrong with how you use matplotlib to achieve what you want to see in your plot.

Answered By: JustLearning

Thanks to everybody who contributed. I have figured out what went wrong. There was nothing wrong with the configuration of the plot. The problem was in the file reading. I was incorrectly reading my data file, so the data being plotted was different from what I was expecting. Fixing the file reading fixed the plot.

Answered By: Harit Krishan
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.