So let's say we have a random variable M and it's continuous. Its PDF function is (4x^3)/81 for 0≤x≤3 and 0 for outside of this interval. And let's say we also have another continuous random variable N that depends on M like N = M^2 + 3. How can I plot the joint CDF of M and N?
Stackoverflow won't let me type this joint CDF derivation in because it thinks it is improperly formatted code, but here is an image of it.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
m = np.linspace(0,3,100)
n = np.linspace(3,12,100)
m_mesh,n_mesh = np.meshgrid(m,n)
joint_cdf = np.minimum(m_mesh,np.sqrt(n_mesh-3))**4/81
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(m_mesh, n_mesh, joint_cdf, cmap=cm.coolwarm,linewidth=0, antialiased=False)
Related
I am trying to plot the following function for values of x between -10 and 10
𝑦=2.5𝑥2+7𝑥+4.2
Click here to see the Maths Equation
I have managed to create an array 𝑥 consisting of 100 equally spaced values between -10 and 10 using the function linspace from numpy.
I'm struggling with how I can substitute the X values generated from the linspace function into the equation to find values for Y and then plot these on graph with a dashed black line instead of a solid blue line.
I know how to do this on paper, but I am struggling to understand which libraries to use in Python for this.
Here is what I have so far:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(start = -10, stop = 10, num = 100)
y = 2.5*x[0]**2 + 7*x[0] + 4.2
Is this what you are looking for? :)
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(start = -10, stop = 10, num = 100)
y = 2.5*x**2 + 7*x + 4.2
plt.plot(x, y, '--', linewidth=2, markersize=12)
plt.show()
It should output this graph
Please write me back if you further face any issues. Cheers...
I'm trying to print a logistic differential equation and I'm pretty sure the equation is written correctly but my graph doesn't display anything.
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
def eq(con,x):
return con*x*(1-x)
xList = np.linspace(0,4, num=1000)
con = 2.6
x= .4
for num in range(len(xList)-1):
plt.plot(xList[num], eq(con,x))
x=eq(con,x)
plt.xlabel('Time')
plt.ylabel('Population')
plt.title("Logistic Differential Equation")
plt.show()
You get nothing in your plot because you are plotting points.
In plt you need to have x array and y array (that have the same length) in order to make a plot.
If you want to do exactly what you are doing I suggest to do like this:
import matplotlyb.pyplot as plt # just plt is sufficent
import numpy as np
def eq(con,x):
return con*x*(1-x)
xList = np.linspace(0,4, num=1000)
con = 2.6
x= .4
y = np.zeros(len(xList)) # initialize an array with the same lenght as xList
for num in range(len(xList)-1):
y[num] = eq(con,x)
x=eq(con,x)
plt.figure() # A good habit is always to use figures in plt
plt.plot(xList, y) # 2 arrays of the same lenght
plt.xlabel('Time')
plt.ylabel('Population')
plt.title("Logistic Differential Equation")
plt.show() # now you should get somthing here
I hope that this helps you ^^
I want to create a customized distribution based on a Levy truncated law, which reads
p(r) = (r + r0)**(-beta)*exp(-r/k).
So I defined it in the following way:
import numpy as np
import scipy.stats as st
class LevyPDF(st.rv_continuous):
def _pdf(self,r):
r0 = 100
k = 1500
beta = 1.6
return (r + r0)**(-beta)*np.exp(-r/k)
Suppose that I want to find the distribution of distances between r = 0 and r = 50km. Then:
nmin = 0
nmax = 50
my_cv = LevyPDF(a=nmin, b=nmax, name='LevyPDF')
x = np.linspace(nmin, nmax, (nmax-nmin)*2)
I do not understand why:
sum(my_cv.cdf(x)) = 2.22
instead of 1.
Then how can I define an histogram of N = 2000000 random distances based on the distribution that I defined?
Using your minimal example (slightly adapted):
import scipy.stats as st
import numpy as np
import matplotlib.pyplot as plt
class LevyPDF(st.rv_continuous):
def _pdf(self,r):
r0 = 100
k = 1500
beta = 1.6
return (r + r0)**(-beta)*np.exp(-r/k)
nmin = 0
nmax = 50
my_cv = LevyPDF(a=nmin, b=nmax, name='LevyPDF')
To sample from your random variable, use rvs() method from rv_continuous class:
N = 50000
X = my_cv.rvs(size=N, random_state=1)
Will return an array of size (N,) with random variates sampled from your distribution. Use random_state option to freeze your example and make your script repeatable (it defines random seed for your sampling).
Note as N softly increases, computation time drastically increases.
To plot histogram, use matplotlib library, see hist:
fig, axe = plt.subplots()
n, bins, patches = axe.hist(X, 50, normed=1, facecolor='green', alpha=0.75)
plt.show(axe)
Bellow a example of sampling from Chi Square with 40 Degrees of Freedom:
from scipy import stats
import numpy as np
import matplotlib.pyplot as plt
rv = stats.chi2(40)
N = 200000
X = rv.rvs(size=N, random_state=1)
fig, axe = plt.subplots()
n, bins, patches = axe.hist(X, 50, normed=1, facecolor='green', alpha=0.75)
plt.show(axe)
It leads to:
I am trying to interpolate spectrogram obtained from matplotlib using scipy's inetrp2d function, but somehow fail to get the same spectrogram. The data is available here
The actual spectrogram is:
And interpolated spectrogram is:
The code looks okay, but even then something is wrong. The code used is:
from __future__ import division
from matplotlib import ticker as mtick
from matplotlib.backends.backend_pdf import PdfPages
import matplotlib.pyplot as plt
import numpy as np
from bisect import bisect
from scipy import interpolate
from matplotlib.ticker import MaxNLocator
data = np.genfromtxt('spectrogram.dat', skiprows = 2, delimiter = ',')
pressure = data[:, 1] * 0.065
time = data[:, 0]
cax = plt.specgram(pressure * 100000, NFFT = 256, Fs = 50000, noverlap=4, cmap=plt.cm.gist_heat, zorder = 1)
f = interpolate.interp2d(cax[2], cax[1], cax[0], kind='cubic')
xnew = np.linspace(cax[2][0], cax[2][-1], 100)
ynew = np.linspace(cax[1][0], cax[1][-1], 100)
znew = 10 * np.log10(f(xnew, ynew))
fig = plt.figure(figsize=(6, 3.2))
ax = fig.add_subplot(111)
ax.set_title('colorMap')
plt.pcolormesh(xnew, ynew, znew, cmap=plt.cm.gist_heat)
# plt.colorbar()
plt.title('Interpolated spectrogram')
plt.colorbar(orientation='vertical')
plt.savefig('interp_spectrogram.pdf')
How to interpolate a spectrogram correctly with Python?
The key to your solution is in this warning, which you may or may not have seen:
RuntimeWarning: invalid value encountered in log10
znew = 10 * np.log10(f(xnew, ynew))
If your data is actually a power whose log you'd like to view explicitly as decibel power, take the log first, before fitting to the spline:
spectrum, freqs, t, im = cax
dB = 10*np.log10(spectrum)
#f = interpolate.interp2d(t, freqs, dB, kind='cubic') # docs for this recommend next line
f = interpolate.RectBivariateSpline(t, freqs, dB.T) # but this uses xy not ij, hence the .T
xnew = np.linspace(t[0], t[-1], 10*len(t))
ynew = np.linspace(freqs[0], freqs[-1], 10*len(freqs)) # was it wider spaced than freqs on purpose?
znew = f(xnew, ynew).T
Then plotting as you have:
Previous answer:
If you just want to plot on logscale, use matplotlib.colors.LogNorm
znew = f(xnew, ynew) # Don't take the log here
plt.figure(figsize=(6, 3.2))
plt.pcolormesh(xnew, ynew, znew, cmap=plt.cm.gist_heat, norm=colors.LogNorm())
And that looks like this:
Of course that still has gaps where its value is negative when plotted on a log scale. What your data means to you when the value is negative should dictate how you fill this in. One simple solution is to just set those values to the smallest positive value and they'd fill in as black:
I've plotted a 3-d mesh in Matlab by below little m-file:
[x,n] = meshgrid(0:0.1:20, 1:1:100);
mu = 0;
sigma = sqrt(2)./n;
f = normcdf(x,mu,sigma);
mesh(x,n,f);
I am going to acquire the same result by utilization of Python and its corresponding modules, by below code snippet:
import numpy as np
from scipy.integrate import quad
import matplotlib.pyplot as plt
sigma = 1
def integrand(x, n):
return (n/(2*sigma*np.sqrt(np.pi)))*np.exp(-(n**2*x**2)/(4*sigma**2))
tt = np.linspace(0, 20, 2000)
nn = np.linspace(1, 100, 100)
T = np.zeros([len(tt), len(nn)])
for i,t in enumerate(tt):
for j,n in enumerate(nn):
T[i, j], _ = quad(integrand, -np.inf, t, args=(n,))
x, y = np.mgrid[0:20:0.01, 1:101:1]
plt.pcolormesh(x, y, T)
plt.show()
But the output of the Python is is considerably different with the Matlab one, and as a matter of fact is unacceptable.
I am afraid of wrong utilization of the functions just like linespace, enumerate or mgrid...
Does somebody have any idea about?!...
PS. Unfortunately, I couldn't insert the output plots within this thread...!
Best
..............................
Edit: I changed the linespace and mgrid intervals and replaced plot_surface method... The output is 3d now with the suitable accuracy and smoothness...
From what I see the equivalent solution would be:
import numpy as np
from scipy.stats import norm
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
x, n = np.mgrid[0:20:0.01, 1:100:1]
mu = 0
sigma = np.sqrt(2)/n
f = norm.cdf(x, mu, sigma)
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_surface(x, n, f, rstride=x.shape[0]//20, cstride=x.shape[1]//20, alpha=0.3)
plt.show()
Unfortunately 3D plotting with matplotlib is not as straight forward as with matlab.
Here is the plot from this code:
Your Matlab code generate 201 points through x:
[x,n] = meshgrid(0:0.1:20, 1:1:100);
While your Python code generate only 20 points:
tt = np.linspace(0, 19, 20)
Maybe it's causing accuracy problems?
Try this code:
tt = np.linspace(0, 20, 201)
The seminal points to resolve the problem was:
1- Necessity of the equivalence regarding the provided dimensions of the linespace and mgrid functions...
2- Utilization of a mesh with more density to make a bee line into a high degree of smoothness...
3- Application of a 3d plotter function, like plot_surf...
The current code is totally valid...