Search code examples
pythonmatplotlibmaxmin

Extracted minimal and maximal values of multiple arrays of every x and y


I am trying to make a list of the minimal and maximal values of 4 different data sets. The data sets are a 4th order polynomial fit of a couple of tests I did in the lab. I have made an example code beneath to show what difficulties are. The arrays of the data sets have different lengths and start at different x-values. This is why I haven't managed to solve this problem with a simple for loop.

The blue and red painted lines show how the minimal and maximum arrays should look like when plotted.

I hope that everything is clear with the example code.

# -*- coding: utf-8 -*-
"""
Created on Mon Oct  4 10:49:21 2021

@author: Lodewijk
"""
import math
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
from numpy import arange

#%% Creating X and Y example values
XTest1=list(range(0,40))
YTest1=np.empty(len(XTest1))
XTest2=list(range(10,40))
YTest2=np.empty(len(XTest2))
XTest3=list(range(2,40))
YTest3=np.empty(len(XTest3))
XTest4=list(range(5,38))
YTest4=np.empty(len(XTest4))
for i in range(len(XTest1)):
    YTest1[i]=math.sin(XTest1[i])
for i in range(len(XTest2)):
    YTest2[i]=3*math.sin(XTest2[i])
for i in range(len(XTest3)):
    YTest3[i]=2*math.sin(XTest3[i])-0.5
for i in range(len(XTest4)):
    YTest4[i]=0.5*math.sin(XTest4[i])+1



plt.plot(XTest1,YTest1, label='Data 1')
plt.plot(XTest2,YTest2, label='Data 2')
plt.plot(XTest3,YTest3, label='Data 3')
plt.plot(XTest4,YTest4, label='Data 4')
plt.legend()
plt.show()
#%% Making a 4th order polynomial best fit graph through the data sets



def objective_4(x,a,b,c,d,e):
    return a * x**4 +b*x**3 +c*x**2+d*x+e 
pars, cov = curve_fit(objective_4, XTest1,YTest1)
x_line1 = arange(min(XTest1), max(XTest1), 1)
a, b, c, d, e = pars
y_line1 = objective_4(x_line1, a, b, c, d, e)

pars, cov = curve_fit(objective_4, XTest2,YTest2)
x_line2 = arange(min(XTest2), max(XTest2), 1)
a, b, c, d, e = pars
y_line2 = objective_4(x_line2, a, b, c, d, e)

pars, cov = curve_fit(objective_4, XTest3,YTest3)
x_line3 = arange(min(XTest3), max(XTest3), 1)
a, b, c, d, e = pars
y_line3 = objective_4(x_line3, a, b, c, d, e)

pars, cov = curve_fit(objective_4, XTest4,YTest4)
x_line4 = arange(min(XTest4), max(XTest4), 1)
a, b, c, d, e = pars
y_line4 = objective_4(x_line4, a, b, c, d, e)

            
plt.plot(x_line1,y_line1, label='Test1')
plt.plot(x_line2,y_line2, label='Test2')
plt.plot(x_line3,y_line3, label='Test3')
plt.plot(x_line4,y_line4, label='Test4')
plt.legend()
plt.show()
    

Solution

  • One option to do that is to pad your data with np.nan to ensure that they all have the same dimension. Once you do that, you can then use np.nanmin and np.nanmax to compute min and max while discarding np.nan values. Overall the code looks like that:

    import math
    import numpy as np
    import matplotlib.pyplot as plt
    from scipy.optimize import curve_fit
    from numpy import arange
    
    #%% Creating X and Y example values
    XTest1=list(range(0,40))
    YTest1=np.empty(len(XTest1))
    XTest2=list(range(10,40))
    YTest2=np.empty(len(XTest2))
    XTest3=list(range(2,40))
    YTest3=np.empty(len(XTest3))
    XTest4=list(range(5,38))
    YTest4=np.empty(len(XTest4))
    for i in range(len(XTest1)):
        YTest1[i]=math.sin(XTest1[i])
    for i in range(len(XTest2)):
        YTest2[i]=3*math.sin(XTest2[i])
    for i in range(len(XTest3)):
        YTest3[i]=2*math.sin(XTest3[i])-0.5
    for i in range(len(XTest4)):
        YTest4[i]=0.5*math.sin(XTest4[i])+1
    
    plt.plot(XTest1,YTest1, label='Data 1')
    plt.plot(XTest2,YTest2, label='Data 2')
    plt.plot(XTest3,YTest3, label='Data 3')
    plt.plot(XTest4,YTest4, label='Data 4')
    plt.legend()
    plt.show()
    #%% Making a 4th order polynomial best fit graph through the data sets
    
    
    
    def objective_4(x,a,b,c,d,e):
        return a * x**4 +b*x**3 +c*x**2+d*x+e 
    pars, cov = curve_fit(objective_4, XTest1,YTest1)
    x_line1 = arange(min(XTest1), max(XTest1), 1)
    a, b, c, d, e = pars
    y_line1 = objective_4(x_line1, a, b, c, d, e)
    
    pars, cov = curve_fit(objective_4, XTest2,YTest2)
    x_line2 = arange(min(XTest2), max(XTest2), 1)
    a, b, c, d, e = pars
    y_line2 = objective_4(x_line2, a, b, c, d, e)
    
    pars, cov = curve_fit(objective_4, XTest3,YTest3)
    x_line3 = arange(min(XTest3), max(XTest3), 1)
    a, b, c, d, e = pars
    y_line3 = objective_4(x_line3, a, b, c, d, e)
    
    pars, cov = curve_fit(objective_4, XTest4,YTest4)
    x_line4 = arange(min(XTest4), max(XTest4), 1)
    a, b, c, d, e = pars
    y_line4 = objective_4(x_line4, a, b, c, d, e)
    
                
    plt.plot(x_line1,y_line1, label='Test1')
    plt.plot(x_line2,y_line2, label='Test2')
    plt.plot(x_line3,y_line3, label='Test3')
    plt.plot(x_line4,y_line4, label='Test4')
    
    ######## Padding start #######
    min_x=min(XTest1[0],XTest2[0],XTest3[0],XTest4[0])
    max_x=max(XTest1[-1],XTest2[-1],XTest3[-1],XTest4[-1])
    x=np.arange(min_x,max_x)
    y_line1_pad=(XTest1[0]-min_x)*[np.nan]+list(y_line1)+(max_x-XTest1[-1])*[np.nan]
    y_line2_pad=(XTest2[0]-min_x)*[np.nan]+list(y_line2)+(max_x-XTest2[-1])*[np.nan]
    y_line3_pad=(XTest3[0]-min_x)*[np.nan]+list(y_line3)+(max_x-XTest3[-1])*[np.nan]
    y_line4_pad=(XTest4[0]-min_x)*[np.nan]+list(y_line4)+(max_x-XTest4[-1])*[np.nan]
    y_line_pad_all=np.array([y_line1_pad,y_line2_pad,y_line3_pad,y_line4_pad])
    
    ####### Compute min and max ######
    min_y=np.nanmin(y_line_pad_all,axis=0)
    max_y=np.nanmax(y_line_pad_all,axis=0)
    
    ####### PLot min and max ######
    plt.plot(x,min_y,color='r',ls='--',lw=2,label='min')
    plt.plot(x,max_y,color='b',ls='--',lw=2,label='max')
    
    plt.legend()
    plt.show()
    

    And the output gives:

    enter image description here