How to convert Uniform normality variables in python? - python

assign x~U(a,b)
get a uniform distribution array:
x_U=uniform(a,b,1000)
There is a normality distribution:
y~N(μ,σ)
I want get array y_N which is correspondently related to x_U elements.
How to carry out in python? It looks like easy in matlab. Such as this link explainnation.
The code as follows is Normality convert to Uniform:
from numpy.random import *
import matplotlib.pyplot as plt
a = normal(25,5.4,1000)
hist_N = plt.hist(a,bins=20,normed=True)
a_cum = np.cumsum(a)
hist_U = plt.hist(a_cum,bins=20,normed=True)
a_cum is uniform correspondent related to a elements
Generating unifrom random number will be applied to Monto-Carlo simulation.But the original parameter is normality distribution.So it needs convertion. My purpose is to inverse above coding process.

If I follow the link in your question, it tells me what to do. I am not sure that the erfinv does, but this code seems to convert a random uniform array to a gaussian shaped array:
import matplotlib.pyplot as plt
import numpy as np
from scipy.special import erfinv
X = np.random.uniform(0,1,1000)
Gauss = lambda x, mu, sigma: mu + np.sqrt(2)*sigma*erfinv(2*X-1)
plt.hist(Gauss(X, 1, 0.2), bins = 20)
plt.show()
Gauss is here a function, made with the lambda statement, which basically works the same as defining a function with def. The function I used is the one that was in your link.
The gaussian shape looks like
and the uniform shape like
.

Related

Generating non-random normally distributed values between two points

I've stumbled across this code in an answer to a question and I'd like to automate the process of getting the distribution to fit neatly between two bounds.
import numpy as np
from scipy import stats
bounds = [0, 100]
n = np.mean(bounds)
# your distribution:
distribution = stats.norm(loc=n, scale=20)
# percentile point, the range for the inverse cumulative distribution function:
bounds_for_range = distribution.cdf(bounds)
# Linspace for the inverse cdf:
pp = np.linspace(*bounds_for_range, num=1000)
x = distribution.ppf(pp)
# And just to check that it makes sense you can try:
from matplotlib import pyplot as plt
plt.hist(x)
plt.show()
Let's say I have the values [720, 965], or any other bounds, that I would like to fit my distribution across. Is there a way to soft-code the adjustment of scale in stats.norm to fit this distribution across my bounds without any unreasonable gaps? Or are there any functions that have this type of functionality?
A scale of ~20 works well for the example code, but I have to adjust it to ~50 for the example of [720, 965]
I am not sure, but truncated normal distribution should be exactly what you are looking for.
from scipy.stats import truncnorm
distr_ab = truncnorm(a, b) # truncated normal distribution in the interval [a, b]
distr_ab.rvs(size=100) # get 100 samples from the distribution
# distr_ab.cdf, distr_ab.ppf etc... all accessible

polyfit error 1d or 2d array needed for y

Click here to see traceback
I have the following question:
Write a Python program to generate data that uses the sum of a random variable (which has a Gaussian distribution) and a 4th-degree polynomial equation (3x4+x3+3x2+4x+5). Using least squares polynomial fit, curve the generated data using a model until your model can accurately predict all values
with the following start on the question:
import random
import numpy as np
import matplotlib.pyplot as plt
def mainFunc():
poly_coeff=[3,1,3,4,5]
poly=np.poly1d(poly_coeff)
print(poly)
y = poly(random.randint(0,10)) + min(10,max(0,random.gauss(2,3)))
x=np.arange(-10,10)
curvefit=np.polyfit(x,y,4)
y_new=np.polyfit(curvefit,x)
plt.plot(x,y, '-or')
plt.plot(x,y_new, '-b')
plt.show()
mainFunc()
Can anyone help with the array error that is being generated?

Gaussian fit in Python plot

I am trying to fit Gaussian function to my Python plot. I have attached the code here. Any corrections would be appreciated!
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
import math
import random
from numpy import genfromtxt
data= genfromtxt ('PVC_Cs137.txt')
plt.xlim(0,2500)
plt.ylim(0,30000)
plt.xlabel("Channel number")
plt.ylabel("Counts")
x = data[:,0]
y = data[:,1]
n = len(x)
mean = sum(x*y)/n
sigma = sum(y*(x-mean)**2)/n
def gaus(x,a,x0,sigma):
return a*exp(-(x-x0)**2/(2*sigma**2))
popt,pcov = curve_fit(gaus,x,y,p0=[1,mean,sigma])
plt.plot(x,gaus(x,*popt))
plt.show()
And here is the link to my file:
https://www.dropbox.com/s/hrqjr2jgfsjs55x/PVC_Cs137.txt?dl=0
There are two problems with your approach. One is related to programming. The gauss fit function has to work with a numpy array. math functions can't provide this functionality, they work with scalars. Therefore your fit functions should look like this
def gauss(x, a, x0, sigma):
return a * np.exp(-(x - x0) ** 2 / (2 * sigma ** 2))
This produces with the right mean/sigma combination a Gauss curve like this
And now we look at the distribution of the values from your file:
This doesn't even vaguely look like a Gauss curve. No wonder that the fit function doesn't converge.
Actually there is a third problem, your calculation of mean/sigma is wrong, but since you can't fit your data to a Gaussian distribution, we can neglect this problem for now.

Graph in logarithmic scale for ordinates for the Jacobi method

I have to program the Jacobi, Gauss Seidel and SOR methods to resolve Ax=b. We use a decomposition A=M-N.
For the Jacobi method, for example, we use M=diag(A) and N=M-A.
I programmed a function
jacobi(A,b,Imax,err,x0)
with the matrix A, the column vector b, a maximum number of iterations Imax, a tolerance err, for the Jacobi method. I used a "stop test" where is the "residual" at the step k.
Here is my code :
import numpy as np
import scipy.linalg as la
def jacobi(A,b,Imax,eps,x0):
M=np.diag(np.diag(A))
N=M-A
r=np.dot(A,x0)-b
x=x0
i=0
err=1+eps
res=[]
while ((i<Imax) and ((la.norm(r))>=eps)):
x=np.dot(np.dot((la.inv(M)),N),x)+np.dot((la.inv(M)),b)
r=np.dot(A,x)-b
err = la.norm(r,2)
res.append(err)
i=i+1
return (x,i,res)
and the test :
A=np.array([[2,0,0],[4,5.4,0],[7,8,9]])
x0=np.array([[1],[1],[1]])
b=np.array([[20],[8],[7]])
print(jacobi(A,b,1000,10**(-3),x0))
Now, I have to represent on a graph (in logarithmic scale for ordinates) the values in function of n.
I just would like to know how to represent a graph in logarithmic scal ? I'm beginner in Python and I don't know how to represent a graph... I tried to be clear, sorry for my bad English...
here is a log plot for some dummy values
import matplotlib.pyplot as plt
import numpy as np
j = np.power(10,range(10)) # <--- here use your computed values instead
plt.plot(j)
plt.yscale('log')
plt.show()
If you want log-log set the xscale as well.

SciPy Cumulative Distribution Function Plotting

I am having troubles plotting a Cumulative Distribution Function.
So far I Have found this:
scipy.stats.beta.cdf(0.2,6,7)
But that only gives me a point.
This will be what I use to plot:
pylab.plot()
pylab.show()
What I want it to look like is this:
File:Binomial distribution cdf.svg
with p = .2 and the bounds stopping once y = 1 or close to 1.
The first argument to cdf can be an array of values, rather than a single value. It will then return an array of values.
import scipy.stats as stats
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0,20,100)
cdf = stats.binom.cdf
plt.plot(x,cdf(x, 50, 0.2))
plt.show()
I don't think the user above, ubuntu, has suggested the right function to use.
Actually his answer is very much misleading and incorrect at large.
Note that binom.cdf() is a function to calculate the cdf of a binomial distribution specified by n and p, Binomial(n,p). That's to say it returns values of the cdf of that random variable for each value in x, rather than the actual cdf function for the discrete distribution specified by vector x.
To calculate cdf for any distribution defined by vector x, just use the histogram() function:
import numpy as np
hist, bin_edges = np.histogram(np.random.randint(0,10,100), normed=True)
cdf = cumsum(hist)
or, just use the hist() plotting function from matplotlib.

Categories