Fit with function that involves integral - python

I am trying to fit a graphic with a function that involves a integral.
If I don't use np.array(), there is a error: "Result from function call is not a proper array of floats."
And if I use np.array(), there is another error: x and y must have same first dimension, but have shapes (501,) and (1,).
How can I fix this?
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from scipy.optimize import curve_fit
import sympy as sp
x1=[1,2,3,4,5]
y=[6,12,18,24,30]
x,a,t=sp.symbols('x a t')
def f(x,a):
return np.array([sp.integrate(t*x*a,(t,0,2))],dtype=float)
xFit=np.arange(0,5.01,0.01)
popt, pcov=curve_fit(f,x1,y)
plt.scatter(x1,y)
plt.plot(xFit,f(xFit,*popt),color="r")
print(popt[0])

The function f(x,a) expects scalar arguments, and returns a scalar value even if x is a vector. Try replacing your plot() line with this:
ystar = [f(_x, popt[0]) for _x in xFit]
plt.plot(xFit, ystar, color="r")

well... it seems to me that this resolved:
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from scipy.optimize import curve_fit
import sympy as sp
x1=[1,2,3,4,5]
y=[6,12,18,24,30]
x,a,t=sp.symbols('x, a, t', real=True)
g=sp.integrate(t*x*a,(t,0,2))
f=sp.lambdify((x,a),g)
xFit=np.arange(0,5.01,0.01)
popt, pcov=curve_fit(f,x1,y)
plt.scatter(x1,y)
ystar = [f(_x, popt[0]) for _x in xFit]
plt.plot(xFit, ystar, color="r")
print(popt[0])

Related

integrating a function through a for loop with appending an array

I am trying to perform an integration through a for loop to generate values for each range but cannot figure out how to append the array at the end.
import numpy as np
from matplotlib import pyplot as plt
from scipy.integrate import quad
import scipy.integrate as integrate
import scipy.special as special
def func(m):
return m**-1.35
mass=np.zeros(49)
for i in range(1,50):
x=mass=integrate.quad(func,i,i+1)
mass.append(x,i)

List of matrices: plot each element of matrix as a function of an index

I have a list of matrices. I would like to plot each element of those matrices in function of another list.
However I am struggling to do it without using a loop.
How can I do it in the simplest way ?
Below a code explaining a little bit more what I want to do.
import numpy as np
from numpy import *
from matplotlib.pyplot import *
import matplotlib.pyplot as plt
from mpmath import *
import mpmath as mpmath
import pylab
import numpy
import time
import math
from qutip.sparse import sp_eigs
import numpy, scipy.io
from random import *
randomMatrixList=[np.random.rand(2,2) for _ in range(10)]
index=np.arange(10)
# I want to plot on x axis: index, on y axis: randomMatrixList[ii][0] for ii
# corresponding to index[ii] for the "0" curve, then randomMatrixList[ii][1] for the first one, and so on
I don't think there is any way to do this completely without loops, but this way is somewhat compact. There is further cleverness to be done if you want, but the code below is a trade off in terms of explicitness and ease to understand.
import numpy as np
import matplotlib.pyplot as plt
randomMatrixList = [np.random.rand(2, 2) for _ in range(10)]
index = np.arange(10)
stacked_matrices = np.array(randomMatrixList)
print(stacked_matrices.shape)
for k in range(stacked_matrices.shape[1]):
for j in range(stacked_matrices.shape[2]):
plt.plot(index, stacked_matrices[:, j, k], label=f"mat[{j},{k}]")
plt.legend()
plt.xlabel("index")
plt.show()
The code produces the image below

Plotting a function with more than one variable in Matplotlib

import numpy as np
import matplotlib.pyplot as plt
import sympy as sym
from ipywidgets.widgets import interact
sym.init_printing(use_latex="mathjax")
x, y, z, t = sym.symbols('x y z t')
We were given a function in class to write as code
\begin{equation}
p_w(z,t)=\frac{1}{\sqrt{\pi \left(1-\exp\left[-2 t\right]\right)}}
\exp\left[-\frac{\left(z-\exp\left[-t\right]\right)^{2}}{1-
\exp\left[-2t\right]}\right]
\end{equation}
which I have written as this
p_w = (1/(sym.sqrt((sym.pi)*(1-(sym.exp(-2*t))))))*(sym.exp((-(z-sym.exp(-t))**2)/(1-sym.exp(-2*t))))
Then find the partial differential equation
∂𝑡𝑝𝑤(𝑧,𝑡)=∂𝑧[𝑧𝑝𝑤(𝑧,𝑡)]+1/2 ∂2𝑧𝑝𝑤(𝑧,𝑡)
which I have written as this:
LHS=sym.diff(p_w,t,1)
#differentiate once with respect to t
RHS=sym.diff(z*p_w,z,1)+((1/2)*(sym.diff(p_w,z,2)))
#now differentiate with respect to z
Now we need to plot it and can only use matplotlib/numpy/sympy libraries.
Plot 𝑝𝑤(𝑧,𝑡) for the three values t=0.1,1,10 in a 𝑝𝑤(𝑧,𝑡) versus z diagram.
Here's what I've got so far:
t_points=[0.1,1,10]
#pw = sym.lambdify(t,p_w)
mytspace=np.linspace(0,10,200)
#myzspace=pw(mytspace)
plt.xlabel("t axis")
plt.ylabel("z axis")
plt.plot(t_array,np.zeros(3),'bs')
I haven't studied multivariable calculus before so I'm a bit lost!
Since one of your variables is given (you know t must be t=0.1, t=1 or t=10) your only variable for plotting is z. I know you are using sympy for the calculations, but for plotting maybe it's simpler to just return p_w as a numpy array. You can define a function to return p_w as so:
import numpy as np
import matplotlib.pyplot as plt
def p_w(z, t):
p_w = (1/(np.sqrt((np.pi)*(1-(np.exp(-2*t))))))*(np.exp((-(z-np.exp(-t))**2)/(1-np.exp(-2*t))))
return p_w
This will give you a numpy array with the results of p_w(z, t) where z is an array and t is just one number. Then you can just iterate over the values of t that you need:
t_points=[0.1, 1, 10]
z = np.linspace(0,10,200)
for t in t_points:
plt.plot(z, p_w(z, t), label='t = {0}'.format(t))
plt.legend()
plt.show()
Result:

I am not able to create the graph for y=sin(x)

enter code here
import numpy as np
import math
import matplotlib.pylab as plt
a=np.linspace(3,6,10)
plt.plot(a,math.sin(a))
plt.show()
The output says ****TypeError: only size-1 arrays can be converted to Python scalars
Use np.sin or np.vectorize(math.sin).
import numpy as np
import math
import matplotlib.pylab as plt
a = np.linspace(3,6,10)
plt.plot(a, np.sin(a))
plt.show()
Note that np.sin, like math.sin, takes radians rather than degrees, so you may want to adjust your array (a) accordingly, or use np.rad2deg because at the moment the result is:
Whereas if you were to pass in floats between 0 and 2 * math.pi, you would get a nice sine wave:

Is there a way to get an r-squared value for nonlinear regression?

I managed to optimize a line in order to get a line of best fit using curve_fit, but I can't seem to get the R squared value the way I can for linear regression, this is my code:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
from scipy.optimize import *
from scipy.integrate import *
from scipy.interpolate import *
df=pd.read_csv('F:/Data32.csv')
df2=df['Temperature']
df3=df['CO2-Rh']
def f(x,a,b,c) :
return a*np.exp(b*x)+c
params, extras = curve_fit(f, df2, df3)
print('a=%g,b=%g, c=%g' %(params[0],df2[1],df3[2]))
plt.plot(df2,df3,'o')
plt.plot(df2,f(df2,params[0],params[1],params[2]))
plt.legend(['data','fit'],loc='best')
plt.show()

Categories