How would one plot the Gaussian pseudo-random noise when N = 2 from the given code below? I don't know how to incorporate N into the formula in the code.
I need to plot for N =1; N = 2; and N=10
Here is the requirement:
Create "size=1000" "N"-sample averages of uniformly distributed random variables. This requires that you generate N * size psuedo-random numbers.
import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
import math
# For reproducibility
np.random.seed(42)
y = np.random.uniform(size=1000)
# Plot the normalized histogram (i.e., the "sample" probability distribution)
facetGrid = sns.displot(y, stat="density", bins=25)
# Note: sns.displot returns a FacetGrid instance -- adding a title is a pain but it can be done
# See the API docs -- https://seaborn.pydata.org/generated/seaborn.FacetGrid.html
facetGrid.fig.suptitle("Gaussian pseudo-random noise")
# Plot a Gaussian PDF using sample mean and variance
sigma = np.std(y)
mu = np.mean(y)
x = np.linspace(np.min(y), np.max(y), 100)
a = 1 / math.sqrt(2 * math.pi) / sigma
x2 = -.5 * ((x - mu) / sigma)**2
y = a * np.exp(x2)
plt.plot(x, y, 'r-', lw=5, alpha=0.6, label='norm pdf');
plt.show()
Here is the plot from the above:
Could you do something like this instead?
# Plot a Gaussian PDF using sample mean and variance
mu = np.mean(y)
sigma = np.std(y)
x = np.linspace(mu - 3 * sigma, mu + 3 * sigma, 100)
plt.plot(x, np.exp(-(x - mu) ** 2 / (2 * sigma ** 2)) / (math.sqrt(2 * math.pi) * sigma), "r-")
Related
I am trying to probability density functions something like the sketch below:
so that the 50th percentile of the distribution has the highest PDF value, and it is at 400. Then the 2.5th and 97.5th percentiles are 320 and 480 respectively. Here is my code I tried:
import numpy as np
mu, sigma = 3, 1. # mean and standard deviation
s = np.random.lognormal(mu, sigma, 480)
import matplotlib.pyplot as plt
count, bins, ignored = plt.hist(s, 100, density=True, align='mid')
x = np.linspace(min(bins), max(bins), 10000)
pdf = (np.exp(-(np.log(x) - mu)**2 / (2 * sigma**2))
/ (x * sigma * np.sqrt(2 * np.pi)))
plt.plot(x, pdf, linewidth=2, color='r')
plt.axis('tight')
plt.show()
The issues I am having is defining the range for the function I want. By placing 480 in the line s = np.random.lognormal(mu, sigma, 480) does not change the shape of the distribution. Secondly, by change the values of mu and sigma, it merely changes the scale on the x axis. Where is my methodology going wrong?
I might misunderstand the question, but in case you are looking for a normal distribution with a mean of 400 and standard deviation of 40, you could use this:
mu, sigma = 400, 40.
s = np.random.normal(mu, sigma, 100000)
count, bins, ignored = plt.hist(s, 1000, density=True)
plt.plot(bins, 1/(sigma * np.sqrt(2 * np.pi)) *
np.exp( - (bins - mu)**2 / (2 * sigma**2) ),linewidth=3, color='r')
I am trying to fit log-normal pdf on the matrix generated using the inbuilt log-normal function but it doesn't fit. I was wondering why it is off. The plot is attached for reference.
import numpy as np
import matplotlib.pyplot as plt
mu, sigma = 0.2, 0.5 # mean and standard deviation
A=np.random.lognormal(mean=0.2, sigma=0.5, size=(10, 10))
count, bins, ignored = plt.hist(A, 100, density=True, align='mid')
x = np.linspace(min(bins), max(bins), 10000)
pdf = (np.exp(-(np.log(x) - mu)**2 / (2 * sigma**2))/ (x * sigma * np.sqrt(2 * np.pi)))
plt.plot(x, pdf, linewidth=2, color='r')
plt.axis('tight')
plt.show()
I have tried to draw a distribution function with a given mean and standard deviation. However, drawing the distribution function only shows the histograms and not the distribution function and I do not know why it is not drawn:
mean = 15.14
stdev = 0.3738
phi = (stdev ** 2 + mean ** 2) ** 0.5
mu = np.log(mean ** 2 / phi)
sigma = (np.log(phi ** 2 / mean ** 2)) ** 0.5
data=np.random.lognormal(mu, sigma , 1000)
mu, sigma, n= lognorm.fit(data)
plt.hist(data, bins=30, density=True, alpha=0.5, color='b')
# Plot the PDF.
xmin, xmax = plt.xlim()
x = np.linspace(xmin, xmax, 1000)
p = lognorm.pdf(x, mu, sigma)
plt.plot(x, p, 'k', linewidth=2)
title = "LogNormal Distribution: Media: {:.2f} y Dev.Est: {:.2f}".format(mean, stdev)
plt.title(title)
plt.show()
The result that I have obtained:
Pay attention to the line:
mu, sigma, n = lognorm.fit(data)
there you are overwriting mu and sigma values used later.
lognorm.pdf(x, mu, sigma) returns zeros because you are evaluating the PDF far away from the mean, where the PDF is actually zero.
In order to properly center the PDF on the mean value, you should replace this line of your code:
p = lognorm.pdf(x, mu, sigma)
with:
p = lognorm.pdf(x = x, scale = mean, s = sigma)
Complete Code
import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import lognorm
mean = 15.14
stdev = 0.3738
phi = (stdev ** 2 + mean ** 2) ** 0.5
mu = np.log(mean ** 2 / phi)
sigma = (np.log(phi ** 2 / mean ** 2)) ** 0.5
data=np.random.lognormal(mu, sigma , 1000)
# mu, sigma, n= lognorm.fit(data)
plt.hist(data, bins=30, density=True, alpha=0.5, color='b')
# Plot the PDF.
xmin, xmax = plt.xlim()
x = np.linspace(xmin, xmax, 1000)
p = lognorm.pdf(x = x, scale = mean, s = sigma)
plt.plot(x, p, 'k', linewidth=2)
title = "LogNormal Distribution: Media: {:.2f} y Dev.Est: {:.2f}".format(mean, stdev)
plt.title(title)
plt.show()
I have been trying to make a plot with some evenly spaced tick in my colorbar, but so far my results always give me a colorbar with the distance between the ticks proportional to their values as shown in the image below:
import numpy as np
import matplotlib
import matplotlib as plt
T= [0.01, 0.02, 0.03, 0.04] #values for the colourbar to use in equation in for loop
x=np.linspace[0, 8, 100]
e=1/(np.exp(x)+1) #factor used in equation dependent on the x-axis values
a=6.4*10**(-9)
b= 1.51 # constants for the equation
pof6= [number **6 for number in T]
norm = matplotlib.colors.Normalize(vmin=np.min(pof6), vmax=np.max(pof6)) #colourbar max and min values
c_m = matplotlib.cm.cool
s_m = matplotlib.cm.ScalarMappable(cmap='jet', norm=norm)
s_m.set_array([])
#below is the for loop that uses one value of T at a time, represented as t in the equation
for t in pof6:
plt.plot(x, b*x/(((a*t*x**2/(m**2))+1)**2)*e, color=s_m.to_rgba(t))
func = lambda x,pos: "{:g}".format(x)
fmt = matplotlib.ticker.FuncFormatter(func)
c_bar=plt.colorbar(s_m, format=fmt, ticks=[0.01**6,0.02* 0.03**6, 0.04**6])
plt.legend()
plt.xlabel('y=E/T')
plt.ylabel('$f_{ν_s}$')
c_bar.set_label(r'T(K)')
plt.show()
I have attempted applying some of the solutions suggested here n=on the website, like Spread custom tick labels evenly over colorbar but haven't been successful at that.
You're using a linear norm, where the pof values are very close to each other. It helps to use a LogNorm. The tick formatter can be adapted to show the values in their **6 format.
The code below shifts the four functions a bit, because with the code from the example all plots seem to coincide. At least when I use something like m=2 (m is not defined in the code).
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import colors as mcolors
from matplotlib import ticker as mticker
T = [0.01, 0.02, 0.03, 0.04] # values for the colourbar to use in equation in for loop
x = np.linspace(0, 8, 100)
e = 1 / (np.exp(x) + 1) # factor used in equation dependent on the x-axis values
a = 6.4 * 10 ** (-9)
b = 1.51 # constants for the equation
pof6 = [number ** 6 for number in T]
norm = mcolors.LogNorm(vmin=np.min(pof6), vmax=np.max(pof6)) # colourbar max and min values
s_m = plt.cm.ScalarMappable(cmap='jet', norm=norm)
s_m.set_array([])
m = 2
for t in pof6:
plt.plot(x, b * x / (((a * t * x ** 2 / (m ** 2)) + 1) ** 2) * e + 10*t**(1/6), color=s_m.to_rgba(t))
func = lambda x, pos: "{:g}**6".format(x**(1/6) )
fmt = mticker.FuncFormatter(func)
c_bar = plt.colorbar(s_m, format=fmt, ticks=pof6)
c_bar.set_label(r'T(K)')
# plt.legend() # there are no labels set, so a default legend can't be created
plt.xlabel('y=E/T')
plt.ylabel('$f_{ν_s}$')
plt.show()
If you want a legend, you need to put a label to each curve, for example:
for t in pof6:
plt.plot(x, b * x / (((a * t * x ** 2 / (m ** 2)) + 1) ** 2) * e, color=s_m.to_rgba(t),
label=f'$t = {t**(1/6):g}^6$')
plt.legend()
I'm trying to generate a single array that follows an exact gaussian distribution. np.random.normal sort of does this by randomly sampling from a gaussian, but how can I reproduce and exact gaussian given some mean and sigma. So the array would produce a histogram that follows an exact gaussian, not just an approximate gaussian as shown below.
mu, sigma = 10, 1
s = np.random.normal(mu, sigma, 1000)
fig = figure()
ax = plt.axes()
totaln, bbins, patches = ax.hist(s, 10, normed = 1, histtype = 'stepfilled', linewidth = 1.2)
plt.show()
If you'd like an exact gaussian histogram, don't generate points. You can never get an "exact" gaussian distribution from observed points, simply because you can't have a fraction of a point within a histogram bin.
Instead, plot the curve in the form of a bar graph.
import numpy as np
import matplotlib.pyplot as plt
def gaussian(x, mean, std):
scale = 1.0 / (std * np.sqrt(2 * np.pi))
return scale * np.exp(-(x - mean)**2 / (2 * std**2))
mean, std = 2.0, 5.0
nbins = 30
npoints = 1000
x = np.linspace(mean - 3 * std, mean + 3 * std, nbins + 1)
centers = np.vstack([x[:-1], x[1:]]).mean(axis=0)
y = npoints * gaussian(centers, mean, std)
fig, ax = plt.subplots()
ax.bar(x[:-1], y, width=np.diff(x), color='lightblue')
# Optional...
ax.margins(0.05)
ax.set_ylim(bottom=0)
plt.show()