Python Taylor series sin function graph - python

I'm trying to draw a Taylor series sin(x) graph using python with Jupyter notebook. I created a short function. The graph will appear correctly until y2, but it will fail at y3. It is difficult to draw a graph with a value of x = 2.7 in y3. I don't know how to fix y3.
This is my code:
import numpy as np
import matplotlib.pyplot as plt
import numpy as np
def f(x) :
result = x - x**3/6 + x**5/120
return result
x = np.linspace(0.0, 7.0, 100)
y = np.sin(x)
y2 = x - x**3/6 + x**5/120
y3 = f(2.7)
plt.title("taylor sin graph")
plt.xlim(0, 7+0.2)
plt.ylim(-5, 5+1)
plt.plot(x, y, label='sin(x)')
plt.plot(x, y2, label='x=0')
plt.plot(x, y3, label='x=2.7')
plt.legend()
plt.show()
I want to add y3 here:

After your comment, it got clarified that you do not need a single point but a horizontal line. In that case you can simply input an x-mesh which has the same value 2.7.
To do so, you first define an array containing values 2.7 by using np.ones(100) * 2.7 and then just pass it to the function.
y3 = f(2.7*np.ones(100))
plt.plot(x, y3, label='x=2.7')
For plotting a single point at x=2.7, there are two ways (among possible others).
First option is to just specify the two x-y numbers and plot using a marker as
plt.plot(2.7, y3, 'bo', label='x=2.7')
Second option is to use plt.scatter. s=60 is just to have a big marker.
plt.scatter(2.7, y3, s=60, label='x=2.7')

import numpy as np
import matplotlib.pyplot as plt
import numpy as np
def f(x) :
result = x - x**3/6 + x**5/120
return result
x = np.linspace(0.0, 7.0, 100)
y = np.sin(x)
y2 = x - x**3/6 + x**5/120
y3 = f(2.7)
plt.title("taylor sin graph")
plt.xlim(0, 7+0.2)
plt.ylim(-5, 5+1)
plt.plot(x, y, label='sin(x)')
plt.plot(x, y2, label='x=0')
plt.plot(2.7, y3, label='x=2.7', marker=11)
plt.legend()
plt.show()
You have to add point - not an array in x-axis and scalar on y-axis.

I think
plt.plot([2.7], [y3], '-o', label='x=2.7')
would work. You can't plot(x,y3) when x is a linspace and y3 is just one number.
Also, Taylor approximation of sin function works only in the interval (-pi, pi).

Related

Plotting x^2 + y^2 = z^2 = 1 using matplotlib without parametric form

I want to plot the unit sphere x^2 + y^2 + z^2 = 1 & I am trying to use sympy , numpy , and matplotlib for the same.
Below is a code snippet:
x,y = sp.symbols('x y')
def g(x,y):
return sqrt(1-x**2 - y**2)
xrange2 = np.linspace(-1, 1, 100)
yrange2 = np.linspace(-1, 1, 100)
X2, Y2 = np.meshgrid(xrange2, yrange2)
Z2 = g(X2, Y2)
Z2[(1- X2**2 - Y2**2 < 0)] = np.nan
Z2[(1- X2**2 - Y2**2 > 0)] = np.nan
ax.plot_surface(X2, Y2, Z2,cmap='Blues', antialiased=True, edgecolor='black')
I don't wish to use parametric equations for the sphere, but rather plot it using x , y and z.
Currently getting below error:
Z contains NaN values. This may result in rendering artifacts.
From the question it is very unclear which version of sqrt is used. Sympy's sqrt certainly won't work. math.sqrt doesn't work on arrays. Only np.sqrt can work. But then, function g needs to be numpy vectorized.
np.sqrt works on arrays, and gives NaN when operated on negative numbers.
ax.plot_surface doesn't want to draw colormapped faces when some of the Z values are NaN, it only draws plain colors in that case. Note that antialiasing doesn't work for plotting faces, only for edges.
To draw a complete sphere, both Z2 and -Z2 need to be drawn.
Due to the NaNs and an equation that doesn't define evenly distributed points, some artifacts will be present. Also, the surfaces will not completely fill up. See this post to draw a sphere via an angular representation.
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
#np.vectorize
def g(x,y):
return np.sqrt(1-x**2 - y**2)
fig = plt.figure()
ax = fig.gca(projection='3d')
xrange2 = np.linspace(-1, 1, 100)
yrange2 = np.linspace(-1, 1, 100)
X2, Y2 = np.meshgrid(xrange2, yrange2)
Z2 = g(X2, Y2)
ax.plot_surface(X2, Y2, -Z2, color='lightblue', antialiased=True, edgecolor='black')
ax.plot_surface(X2, Y2, Z2, color='lightblue', antialiased=True, edgecolor='black')
plt.show()
PS: Note that you are not really using sympy in the code (def g(x,y) uses its own version of standard Python variables x and y). Also, mixing numpy and sympy doesn't work. This related post handles plotting a surface as parametric surface via sympy. Note that these parametric surfaces only work for 2 variables, in this case x, y and z are defined in function of phi and theta. As far as I am aware, plotting a general 3D equation doesn't work with sympy at the moment.

2D plot xy-lists of different length

I have an arbitrary, large number (50-1000) of lists, representing X and Y coordinates, I'd like to plot them in one figure.
The lists are of different length, usually 100-1000 elements each. I get the lists as pairs of x and y coordinates (see example), but could easily convert them to 2xN arrays. They need to be plotted in order, from first to the last element. Each line separately.
Is there a way to pack all my lists to one (or two; x and y) object that matplotlib can read?
This example gives the wanted output but is unhandy when there is a lot of data.
I'm happy for a solution that takes advantage of numpy.
from matplotlib import pyplot as plt
fig, ax = plt.subplots(1,1)
x1 = [1,2,5] # usually much longer and a larger number of lists
y1 = [3,2,4]
x2 = [1,6,5,3]
y2 = [7,6,3,2]
x3 = [4]
y3 = [4]
for x, y, in zip([x1, x2, x3],[y1, y2, y3]):
ax.plot(x,y, 'k.-')
plt.show()
I would prefer something like this:
# f() is the function i need, to formats the data for plotting
X = f(x1, x2, x3)
Y = f(y1, y2, y3)
#... so that I can do some processing of the arrays X, and Y here.
ax.plot(X, Y, 'k.-')
You can use a LineCollection for that. Unfortunately, if you want to have markers in your lines, LineCollection does not support that, so you would need to do some trick like adding a scatter plot on top (see Adding line markers when using LineCollection).
from matplotlib import pyplot as plt
from matplotlib.collections import LineCollection
fig, ax = plt.subplots(1,1)
x1 = [1,2,5]
y1 = [3,2,4]
x2 = [1,6,5,3]
y2 = [7,6,3,2]
x3 = [4]
y3 = [4]
# Add lines
X = [x1, x2, x3]
Y = [y1, y2, y3]
lines = LineCollection((list(zip(x, y)) for x, y in zip(X, Y)),
colors='k', linestyles='-')
ax.add_collection(lines)
# Add markers
ax.scatter([x for xs in X for x in xs], [y for ys in Y for y in ys], c='k', marker='.')
# If you do not use the scatter plot you need to manually autoscale,
# as adding the line collection will not do it for you
ax.autoscale()
plt.show()
If you are working with arrays, you may also do as follows:
import numpy as np
# ...
X = [x1, x2, x3]
Y = [y1, y2, y3]
lines = LineCollection((np.stack([x, y], axis=1) for x, y in zip(X, Y)),
colors='k', linestyles='-')
ax.add_collection(lines)
ax.scatter(np.concatenate(X), np.concatenate(Y), c='k', marker='.')

Calculation of areas between two curves

I have a code contain a curve and a line. I know how to fill the areas below and under the line but I need to calculate the areas values of each one.
Here is the code:
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0.0, 2, 0.01)
y1 = np.sin(2*np.pi*x)
y2 = 0*x
fig, ax = plt.subplots(1, 1, sharex=True)
ax.plot(x, y1, x, y2, color='black')
ax.fill_between(x, y1, y2, where=y2 >= y1, facecolor='green', interpolate=True)
ax.fill_between(x, y1, y2, where=y2 <= y1, facecolor='red', interpolate=True)
plt.show()
Any help?
Adapted from the scipy.integrate.quad docs example for a different function, y = x^2:
from scipy import integrate
def f(x):
return x**2
integrate.quad(f, 0, 4)
# (21.333333333333332, 2.3684757858670003e-13)
print(4**3 / 3.) # analytical result
# 21.3333333333
The result and an error for the numerical calculation is returned.
If you want an exact or symbolic answer, consider sympy. Here is a similar example applied to y = πx^2 (Note: leading underscores were used here to distinguish Sympy objects).
import sympy as sym
sym.init_printing()
_x = sym.symbols("x")
_f = sym.pi * _x**2
sym.integrate(_f, (_x, 0, 2))
Apply either of these techniques to your problem.
This is called numerical-integration.
There's a bunch of standard methods. As #pylang said they're already implemented in scipy.integrate.* . scipy.integrate.quad is Gaussian quadrature.

Wire_frame in matplotlib 1.5 doesn't plot correctly

I am trying to plot a wireframe using plot_wireframe from the Axes3D module. My dataset: three 2D arrays: two created with np.arange and then np.meshgrid. The third one is an array containing results of function "f2" (f2 = f(x, y)). I expected 3D plot, but result is 2D plot in 3D space. Now I made some code that looks like a part of documantation of mpl, but still doesn't work. Code:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
def f2(x, y):
'''Return f(x, y) = exp(-(x * x + y * y)) * sin(-5. * (x * x + y * y))'''
return np.exp(-(x**2 + y**2)) * np.sin(-5.0 * (x**2 + y**2))
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x2 = np.arange(-1.5, 1.5, 0.02)
y2 = np.arange(1.5, -1.5, -0.02)
X, Y = np.meshgrid(x2, y2)
z2 = f2(X, Y)
ax.plot_wireframe(X, X, z2, rstride=10, cstride=10, linewidth=0.1,
label='$\exp(-(x^2 + y^2)){sin}(-5.0(x^2 + y^2)$')
plt.show()
That is what I want:
Beautiful 3D plot
But the reality is cruel:
"A plot I've got"
I have no idea what I'm doing wrong. Is it a problem with values of vectors?
Change
ax.plot_wireframe(X, X, z2, rstride=10, cstride=10, linewidth=0.1,
label='$\exp(-(x^2 + y^2)){sin}(-5.0(x^2 + y^2)$')
to
ax.plot_wireframe(X, Y, z2, rstride=10, cstride=10, linewidth=0.1,
label='$\exp(-(x^2 + y^2)){sin}(-5.0(x^2 + y^2)$')
You are using X instead of Y as the second argument to ax.plot_wireframe. Thus, all points fall on top of the diagonal Y=X.

Label Areas in Python Matplotlib stackplot

I would like to generate labels inside the areas of a matplotlib stackplot. I would settle for labeling a line used to bound the area. Consider the example:
import numpy as np
from matplotlib import pyplot as plt
fnx = lambda : np.random.randint(5, 50, 10)
x = np.arange(10)
y1, y2, y3 = fnx(), fnx(), fnx()
areaLabels=['area1','area2','area3']
fig, ax = plt.subplots()
ax.stackplot(x, y1, y2, y3)
plt.show()
This produces:
But I would like to produce something like this:
The matplotlib contour plots have this type of labeling functionality (though the lines are labeled in the case of the contour plot).
Any help (or even redirection to a post I might have missed) is appreciated.
Ah, heuristics. Something like this?:
import numpy as np
from matplotlib import pyplot as plt
length = 10
fnx = lambda : np.random.randint(5, 50, length)
x = np.arange(length)
y1, y2, y3 = fnx(), fnx(), fnx()
areaLabels=['area1','area2','area3']
fig, ax = plt.subplots()
ax.stackplot(x, y1, y2, y3)
loc = y1.argmax()
ax.text(loc, y1[loc]*0.25, areaLabels[0])
loc = y2.argmax()
ax.text(loc, y1[loc] + y2[loc]*0.33, areaLabels[1])
loc = y3.argmax()
ax.text(loc, y1[loc] + y2[loc] + y3[loc]*0.75, areaLabels[2])
plt.show()
which in test runs is okayish:
Finding the best loc could be fancier -- maybe one wants the x_n, x_(n+1) with the highest average value.

Categories