Matplotlib padding between plot and axis - python

I am trying to do a matplolib figure with some padding between the axis and the actual plot.
Here is my example code :
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1)
x = np.linspace(0, 1)
y = np.sin(4 * np.pi * x) * np.exp(-5 * x)
plt.plot(x, y, 'r')
plt.grid(True)
plt.show()
And here is what I am trying to get :

In your case, it's easiest to use ax.margins(some_percentage) or equivalently plt.margins(some_percentage).
For example:
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
x = np.linspace(0, 1)
y = np.sin(4 * np.pi * x) * np.exp(-5 * x)
ax.plot(x, y, 'r')
ax.grid(True)
ax.margins(0.05) # 5% padding in all directions
plt.show()

you can set the limits of the plot with xlim and ylim.
See here

Related

Scatter plot with a circle in it

I was planning to do a scatter plot with 5000 data points with a line of unit circle in the same plot, but the code I have right now show a pretty small plot with huge dots in it. I tried to make this plot size larger but plt.figure(figsize=(12,12)) doesn't work....wonder what did I do wrong?
import numpy as np
import scipy.stats
import matplotlib.pyplot as plt
x=scipy.stats.uniform.rvs(loc=-1, scale=2, size=5000)
y=scipy.stats.uniform.rvs(loc=-1, scale=2, size=5000)
a=np.cos(np.linspace(0, 2*np.pi, 200))
b=np.sin(np.linspace(0, 2*np.pi, 200))
plt.scatter(x,y)
plt.plot(a,b, color="red")
plt.figure(figsize=(12,12))
plt.show()
plt.figure() creates a new empty plot. You should call it before the other plotting functions
You can set a smaller dotsize, e.g plt.scatter(x, y, s=1). To force that the circle is shown as a circle, set an equal aspect ratio (set_aspect('equal')).
import numpy as np
import scipy.stats
import matplotlib.pyplot as plt
x = scipy.stats.uniform.rvs(loc=-1, scale=2, size=5000)
y = scipy.stats.uniform.rvs(loc=-1, scale=2, size=5000)
a = np.cos(np.linspace(0, 2 * np.pi, 200))
b = np.sin(np.linspace(0, 2 * np.pi, 200))
plt.figure(figsize=(12, 12))
plt.scatter(x, y, s=1)
plt.plot(a, b, color="red")
plt.gca().set_aspect('equal')
plt.show()
To change the figsize after the plot has been created, you can use:
fig = matplotlib.pyplot.gcf()
fig.set_size_inches(15, 15)
Matplotlib also provides a function to create a circle. Here is an example setting a semi-transparent facecolor:
import scipy.stats
import matplotlib.pyplot as plt
x = scipy.stats.uniform.rvs(loc=-1, scale=2, size=5000)
y = scipy.stats.uniform.rvs(loc=-1, scale=2, size=5000)
plt.figure(figsize=(12, 12))
plt.scatter(x, y, s=1)
ax = plt.gca()
ax.add_patch(plt.Circle((0, 0), 1, facecolor='#FF000011', edgecolor='red'))
ax.set_aspect('equal')
plt.show()

python - how do I fix interpolate grid origin issues in matplotlib?

I have a data set with a small sample size of data. For example:
My code looks something like this:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.interpolate import Rbf
df=pd.read_csv('test.csv')
df.head()
extent = x_extent = x_min, x_max, y_min, y_max = [df["X"].min()-1000, df["X"].max()+1000, df["Y"].min()-1000, df["Y"].min()+1000]
grid_x, grid_y = np.mgrid[x_min:x_max:100, y_min:y_max:100]
rbfi=Rbf(df["X"], df["Y"], df["Total"])
di=rbfi(grid_x, grid_y)
plt.scatter(grid_x, grid_y, s=10)
plt.figure(figsize=(15,15))
plt.imshow(di.T, origin="lower", extent=extent)
c2 = plt.scatter(df["X"], df["Y"], s=60, c=df["Total"], edgecolor='#ffffff66')
plt.colorbar(c2, shrink=0.6)
plt.show()
the result:
The result is a scatter plot of my points that appear to be in the correct place, but the interpolated grid is not covering the scatter points. So I think this has something to do with my origin not being correct, but I don't know how to fix this.
Two approaches here, one with a Delaunay triangulation, the other using the Radial Basis Function. Snippet and figure below.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.tri import Triangulation
from scipy.interpolate import Rbf
rng = np.random.default_rng()
X = rng.random(size=(15))
Y = rng.random(size=(15))
Total = rng.random(size=(15))
fig, (ax, bx) = plt.subplots(nrows=1, ncols=2, num=0, figsize=(16, 8))
tri = Triangulation(X, Y)
tctrf = ax.tricontourf(tri, Total)
gridY, gridX = np.mgrid[np.amin(Y):np.amax(Y):100 * 1j,
np.amin(X):np.amax(X):100 * 1j]
rbfi = Rbf(X, Y, Total, function='linear')
iTotal = rbfi(gridX, gridY)
bx.contourf(gridX, gridY, iTotal)
scat = ax.scatter(X, Y, s=60, c=Total, edgecolor='black')
fig.colorbar(scat, ax=ax)
scat = bx.scatter(X, Y, s=60, c=Total, edgecolor='black')
fig.colorbar(scat, ax=bx)
ax.set_aspect('equal')
bx.set_aspect('equal')
fig.tight_layout()
fig.savefig('so.png')
plt.show()

How to do a 3D plot of gaussian using numpy?

I'm trying to plot a gaussian function using numpy.
the funtion is z=exp(-(x2+y2)/10) but I only get a 2D function
import numpy as np
from matplotlib import pyplot as plt
x=np.linspace(-10,10, num=100)
y=np.linspace(-10,10, num=100)
z=np.exp(-0.1*x**2-0.1*y**2)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_wireframe(x,y,z)
I obtain:
but I want to obtain:
I'm using numpy becouse I need the set of data.
You need to obtain the correct dimensions. This can be done using meshgrid. Also, your desired plot is a surface plot, not a wireframe (though you can do that too).
# import for colormaps
from matplotlib import cm
x=np.linspace(-10,10, num=100)
y=np.linspace(-10,10, num=100)
x, y = np.meshgrid(x, y)
z = np.exp(-0.1*x**2-0.1*y**2)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(x,y,z, cmap=cm.jet)
plt.show()
given the original formula of a gaussian distribution I wrote the following code:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D # <--- This is important for 3d plotting
A = 1
x0 = 0
y0 = 0
sigma_X = 2
sigma_Y = 2
xg = np.linspace(-5,5,num=100)
yg = np.linspace(-5,5,num=100)
theta= np.pi
X, Y = np.meshgrid(xg,yg)
a = np.cos(theta)**2/(2*sigma_X**2) + np.sin(theta)**2/(2*sigma_Y**2);
b = -np.sin(2*theta)/(4*sigma_X**2) + np.sin(2*theta)/(4*sigma_Y**2);
c = np.sin(theta)**2/(2*sigma_X**2) + np.cos(theta)**2/(2*sigma_Y**2);
aXXdet = np.array([a*(Xi-x0)**2 for Xi in X],float)
bbXYdet = np.array([2*b*(Xi-x0)*(Y[ii]-y0) for ii,Xi in enumerate(X)],float)
cYYdet = np.array([c*(Yi-y0)**2 for Yi in Y],float)
Z = np.array([A*np.exp( - (ai + bbXYdet[i] + cYYdet[i])) for i,ai in enumerate(aXXdet)],float);
# plot
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(X, Y, Z, cmap=cm.coolwarm)
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
plt.show()
which also plots the distribution. So you could play around with the parameters and see their effect!

How to display the result value outside the axes box

I plotted the picture using the code below.
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(6)
fig = plt.figure()
ax = plt.subplot(111)
for i in xrange(5):
ax.set_xlim(0, 3)
ax.set_ylim(0, 10)
ax.plot(x, i * x)
plt.show()
This is the result picture.
enter image description here
This is the picture I want to see.
I want to get the results out of the box area.
How can you draw such a plot?
enter image description here
This should work -
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(6)
fig = plt.figure()
ax = plt.subplot(111)
for i in xrange(5):
ax.set_xlim(0, 3)
ax.set_ylim(0, 10)
ax.plot(x, i * x)
if 3*i >10:
ytx = 10.5
xtx = 10.0/i
else:
ytx = 3*i
xtx = 3.05
tx = plt.text(xtx, ytx, str(i), fontsize=18, color='black')
plt.show()
This generates -

matplotlib surface plot extends past axis limits

How do I make a nice paraboloid in Matplotlib that looks like
All I can get is this,
where the top is not "cut off". I've tried just dropping all values of the Z array outside of the radius of the parabola at the top, but that gives very jagged edges. Can someone help me?
Here is my code:
from matplotlib import *
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
from pylab import *
import math
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
X = np.arange(-5, 5, 0.1)
Y = np.arange(-5, 5, 0.1)
X, Y = np.meshgrid(X, Y)
Z = (X**2 + Y**2)
ax.set_zlim(-10, 20)
ax.plot_surface(X, Y, Z, alpha=0.9, rstride=4, cstride=4, linewidth=0.5, cmap=cm.summer)
plt.show()
For future reference, I had a thought to parametrize the surface in cylindrical coordinates, and it looks exactly how I want it:
from matplotlib import *
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
from pylab import *
import math
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
r = T = np.arange(0, 2*pi, 0.01)
r, T = np.meshgrid(r, T)
#Parametrise it
X = r*np.cos(T)
Y = r*np.sin(T)
Z = r**2
ax.plot_surface(X, Y, Z, alpha=0.9, rstride=10, cstride=10, linewidth=0.5, cmap=cm.summer)
plt.show()
I guess it makes sense: when working with a cylindrical object, use cylindrical coordinates!
Manual data clipping
One approach I've seen that works is to manually clip the data; e.g. your example would be updated to
from matplotlib import *
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
from pylab import *
import math
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
X = np.arange(-5, 5, 0.1)
Y = np.arange(-5, 5, 0.1)
X, Y = np.meshgrid(X, Y)
Z = (X**2 + Y**2)
ax.set_zlim(-10, 20)
for i in range(len(X)):
for j in range(len(Y)):
if (Z[j,i] < -10) or (Z[j,i] > 20):
Z[j,i] = NaN
ax.plot_surface(X, Y, Z, alpha=0.9, rstride=4, cstride=4, linewidth=0.5, cmap=cm.summer)
plt.show()
Note
This can be done concisely for this case using
Z[Z>20] = NaN
Resulting in

Categories

Resources