I am trying to calculate the derivative of a function using NumPy (I know it would be easier to use SciPy but I am trying to learn how to do this).
So far I have been able to plot the original function, but I'm unsure how to calculate the derivative.
import numpy as np
import matplotlib.pyplot as plt
def myFunction(a):
b=np.sin(x)/(x-0.05)
return b
x=np.arange(-10.0,10.0,1.0)
y=myFunction(x)
nx=len(x)
xval=np.array([],dtype='float')
print('len(xval=',len(xval),' xval=',xval)
for i in np.arange(0,nx-1,1):
a=(y[i 1]-y[i])/(x[i 1]-x[i])
if a< 0.0 :
b=(y[i 1]-y[i])/(x[i 1]-x[i])
xval=np.append(xval,[b])
elif y[i] == 0.0:
b=x[i]
xval=np.append(xval,[b])
print('solution(xval)=',xval)
yval=myFunction(xval)
plt.plot(x,y,"b")
xa=[-10.0,10.0]
ya=[0.0,0.0]
plt.plot(xa,ya,"r")
yval=myFunction(xval)
plt.plot(xval,yval,'o')
plt.show()
ValueError: x and y must have same first dimension, but have shapes (10,) and (20,)
The error is referring to
plt.plot(xval,yval,'o')
What does it mean by dimensions and shapes? And I also included the plot it made but it's not correct, its just a weird version of the normal Sin function and not its derivative. Also, what is in the code that makes the graph look like a bunch of line segments?
CodePudding user response:
If we take this bit of code:
xval=np.array([],dtype='float')
for i in np.arange(0,nx-1,1):
a=(y[i 1]-y[i])/(x[i 1]-x[i])
if a< 0.0 :
b=(y[i 1]-y[i])/(x[i 1]-x[i])
xval=np.append(xval,[b])
elif y[i] == 0.0:
b=x[i]
xval=np.append(xval,[b])
You are going about things the right way to calculate derivatives, but essentially you don't really need the if...elif
statements at all (these statements in your code will mean that derivatives are not stored for all values of x
as they do not cover all cases). The value a
is the derivative in all cases, so you just need to append that into your array. To avoid confusion, I'd suggest calling xval
something like dydx
as it is not giving positions on the x-axis, e.g.:
dydx = np.array([],dtype='float')
for i in np.arange(0,nx-1,1):
# calculate the derivative
a = (y[i 1] - y[i]) / (x[i 1] - x[i])
dydx = np.append(dydx, [a])
You could then plot x
vs dydx
, but noting that x
will be one longer than dydx
. So, you could either use plt.plot(x[1:], dydx)
, which will use x values starting from the second value within x
to the end, or plt.plot(x[:-1], dydx)
.
@mkrieger1's answer and my comment provide the reason behind the shape of the arrays being discrepant.
CodePudding user response:
The problem is that xval
and yval
have different number of elements (xval
has 10 elements, yval
has 20 elements). But in order create a plot, plt.plot
needs two arrays which have the same number of elements.
Normally you would expect that by
yval=myFunction(xval)
they both have the same number of elements, since each value in xval
is transformed to one value in yval
.
However,
def myFunction(a):
b=np.sin(x)/(x-0.05)
return b
myFunction
does not actually transform the array xval
(which is known inside the function as a
), but the array x
, which is defined above the function as x=np.arange(-10.0,10.0,1.0)
and has a different number of elements than xval
.
So you should make sure that inside the function, you are actually using the array that is passed in, instead of the x
array from the global scope:
Either rename the function argument a
to x
, or change b=np.sin(x)/(x-0.05)
to b=np.sin(a)/(a-0.05)
in the function.