Issue
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:
Answered By - jylls
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.