ChiDist excel function in python - python

I have an excel function that i'm trying to replicate into python but struggling to replicate it. Here's the function (VBA):
Function Z(Lambda, conf) As Integer
Application.Volatile
Lambda = Application.Round(Lambda, 3)
Select Case Lambda
Case Is < 400
For i = 0 To 500
' v = Application.Poisson(i, Lambda, True)
v = Application.ChiDist(2 * Lambda, 2 * i + 2)
If v >= conf Then
Z = i
Exit Function
End If
Next
Case Else
Z = Application.NormInv(conf, Lambda, Sqr(Lambda))
End Select
End Function
In Excel if i run =z(2,95%), i get z=5
I thought I could use:
from scipy import stats
stats.chi2.cdf
but not getting far with it.
Any help is highly appreciated!

According to the ChiDist docs, (see also CHIDIST), ChiDist returns the right tail of the Χ² distribution. The corresponding function in SciPy is the sf (survival function) method of scipy.stats.chi2. In your Python code, change stats.chi2.cdf to stats.chi2.sf.

Managed to get the function working in python - thanks #Warren Weckesser for the guidance on the chi2.sf.
from scipy.stats import norm, chi2
def z(lamda_calc, prob):
if lamda_calc < 400:
z_calc = [i for i in range (0,500) if chi2.sf(2 * lamda_calc, 2 * i + 2) >=
prob][0]
else:
z_calc = int(norm.ppf(prob,lamda_calc,sqrt(lamda_calc)))
return z_calc
print
print ("z:'", z(1.4, 0.98))

Related

How do I optimize a simple multivariate function in economics

I apologize if this is simple but I have looked for over an hour and nothing has worked. I am attempting to use python to find the optimal level of L (Labor) and the output (Profit) given the objective function 5(12*L*K - 0.1*L^2*K) - 5*L - 5*K when K is fixed at 10.
I have tried to use the following code from other answers to similar questions (using the '-' to maximize).
def micro(L):
return 5(12*L*10 - 0.1*L**2*10) - 5*L - 5*10
results = minimize(-micro, 0)
I'm still new to python so I could just be completely off base. Thanks for the help!
scipy.optimize.fmin can do this:
>>> from scipy.optimize import fmin
>>> def fn(x):
... return -(-5*x*x+595*x-10)
...
>>> fmin(fn,0)
Optimization terminated successfully.
Current function value: -17651.250000
Iterations: 37
Function evaluations: 74
[59.5]
>>>
By using np.arange we create a NumPy array from 0 to 100 each time increasing by 0.1 then we plug it into the profit equation and we use np.argmax to return the index of the biggest profit witch will get us how much labor you have to do for it.
import numpy as np
def find_optimal_L():
L = np.arange(0, 100, 0.1)
profit = 5*(12*L*10 - 0.1*L**2*10) - 5*L - 5*10
return L[np.argmax(profit)], np.max(profit)
L,profit = find_optimal_L()
print(L,profit)
This is other option:
my_results = []
def micro(L):
result = 5*(12*L*10 - 0.1*L**2*10) - 5*L - 5*10
my_results.append(result)
return np.amax(my_results)
You can change the range here:
L = np.linspace(-100, 100, 1000)
micro(L)
17651.232263294325 # Output
If you want to minimise, just change the return:
return np.amin(my_results) # -109550.0 Output

TypingError for Numba

I have this piece code, using Numba to speed up processing. Basically, particle_dtype is defined to make code ran using Numba. However, TypingError is reported, saying "Cannot determine Numba type of <class 'function'>". I cannot figure out where is the problem.
import numpy
from numba import njit
particle_dtype = numpy.dtype({'names':['x','y','z','m','phi'],
'formats':[numpy.double,
numpy.double,
numpy.double,
numpy.double,
numpy.double]})
def create_n_random_particles(n, m, domain=1):
parts = numpy.zeros((n), dtype=particle_dtype)
parts['x'] = numpy.random.random(size=n) * domain
parts['y'] = numpy.random.random(size=n) * domain
parts['z'] = numpy.random.random(size=n) * domain
parts['m'] = m
parts['phi'] = 0.0
return parts
def distance(se, other):
return numpy.sqrt(numpy.square(se['x'] - other['x']) +
numpy.square(se['y'] - other['y']) +
numpy.square(se['z'] - other['z']))
parts = create_n_random_particles(10, .001, 1)
#njit
def direct_sum(particles):
for i, target in enumerate(particles):
for j in range(particles.shape[0]):
if i == j:
continue
source = particles[j]
r = distance(target, source)
# target['phi'] += source['m'] / r
target['phi'] = target['phi'] + source['m'] / r
return(target['phi'])
print(direct_sum(parts) )
I guess it's because non-supported functions or operations are used somewhere, but I cannot find it. Thanks for your help.
direct_sum which is a JITed function cannot call distance because it is not JITed (pure-Python function). You need to use the decorator #njit on distance too.

Multiplying two arrays in python with different lenghts

I want to know if it's possible to solve this problem. I have this values:
yf = (0.23561643, 0.312328767, 0.3506849315, 0.3890410958, 0.4273972602, 0.84931506)
z = (4.10592285e-05, 0.0012005020, 0.00345332906, 0.006367483, 0.0089151571, 0.01109750, 0.01718827)
I want to use this function (Discount factor) but it's not going to work because of the different lenghts between z and yf.
def f(x):
res = 1/( 1 + x * yf)
return res
f(z)
output: ValueError: cannot evaluate a numeric op with unequal lengths
My question is that if it exists a way to solve this. The approximate output values are:
res = (0.99923, 0.99892, 0.99837, 0.99802, 0.99763, 0.99175)
Any help with this will be perfect and I want to thanks in advance to everyone who takes his/her time to read it or try to help.
Do you want array to broadcast to the whichever is the shorter? You can do this
def f(x):
leng = min(len(x), len(yf))
x = x[:leng]
new_yf = yf[:leng] # Don't want to modify global variable.
res = 1/( 1 + x * new_yf)
return res
and it should work.
Find the minimum length and iterate. Can also covert to numpy arrays and that would avoid a step of iteration
import numpy as np
yf = (0.23561643, 0.312328767, 0.3506849315, 0.3890410958, 0.4273972602, 0.84931506)
z = (4.10592285e-05, 0.0012005020, 0.00345332906, 0.006367483, 0.0089151571, 0.01109750, 0.01718827)
x=min(len(yf),len(z))
res = 1/( 1 + np.array(z[:x]) * np.array(yf[:x]))
using numpy.multiply
res = 1/( 1 + np.multiply(np.array(z[:x]),np.array(yf[:x])))

python a loop to a single line

I have the following code:
from django.db.models import Sum, F, FloatField
from data.models import Plant, Recording
for plant in Plant.objects.all():
total_ecof=0
total_ectr=0
for recording in Recording.objects.filter(plant__id=plant.id):
total_ecof = total_ecof + (recording.performance_loss*recording.multiplier*recording.occurrence*plant.no_modules)/(plant.nominal_power*recording.years_of_operation*plant.nominal_power)
total_ectr = total_ectr + ((10 + 15 + 200 + 50)*recording.occurrence+240*50*recording.occurrence*plant.no_modules)/(plant.nominal_power*3)
print(total_ecof)
print(total_ectr)
The result is:
0.00018
10800.049500000001
0.0002666666666666667
16000.073333333334
6.666666666666667e-05
4000.0183333333334
The questions is:
I am pretty sure that there is a single line code doing the same, please let me know.
If you define a lambda that computes your local_ecof (or local_ectr), then you can use the map(lambda, list) function to apply the computation to all elements of the list, then use a reduce(lambda x, y : x + y) to sum them all.

Converting recursive algorithm to Iterative

I have done the Recursive function in Python that works:
def Rec(n):
if (n<=5):
return 2*n
elif (n>=6):
return Rec(n-6)+2*Rec(n-4)+4*Rec(n-2)
print (Rec(50))
But I can't think of an iterative one
I am sure I will need to use a loop and possibly have 4 variables to store the previous values, imitating a stack.
For your particular question, assuming you have an input n, the following code should calculate the function iteratively in python.
val = []
for i in range(6):
val.append(2*i)
for i in range(6,n+1):
val.append( val[i-6] + 2*val[i-4] + 4*val[i-2] )
print(val[n])
I get this answer:
$ python test.py
Rec(50) = 9142785252232708
Kist(50) = 9142785252232708
Using the code below. The idea is that your function needs a "window" of previous values - Kn-6, Kn-4, Kn-2 - and that window can be "slid" along as you compute new values.
So, for some value like "14", you would have a window of K8, K9, ... K13. Just compute using those values, then drop K8 since you'll never use it again, and append K14 so you can use it in computing K15..20.
def Rec(n):
if (n<=5):
return 2*n
elif (n>=6):
return Rec(n-6)+2*Rec(n-4)+4*Rec(n-2)
def Kist(n):
if n <= 5:
return 2 * n
KN = [2*n for n in range(6)]
for i in range(6, n+1):
kn = KN[-6] + 2 * KN[-4] + 4 * KN[-2]
KN.append(kn)
KN = KN[-6:]
return KN[-1]
print("Rec(50) =", Rec(50))
print("Kist(50) =", Kist(50))

Categories