Changing only the calculation in a function - python

Is it possible to have a function where you specify a function within it as a variable.
For example, I have two functions which follow exactly the same process, except one calculaate the Average using np.mean and the other calculates the standard deviation where only np.std is different.
i.e.
it would be defined:
def calculate(function)
you would call one in the script like:
calculate(mean)
and the other
calculate(std)
I'm just wondering if it is possible to do something like this s it would greatly reduce my script length.
EDIT
Sorry I should have said that I wanted the mean and std to be the ones predefined in numpy. getattr() in Xu's answer worked

Use getattr to get the method object according to the method name:
def calculate(function):
func = getattr(np, function)
func(...) # do what you want
calculate("mean") # calculate the average number
calculate("std") # calculate the standard deviation

Yes this is possible.
Example:
def addIt(x):
return x+x
def test(fn):
for x in xrange(5):
print fn(x)
test(addIt)
Output:
0
2
4
6
8

def f1(t): return t * 2
def f2(t): return t * t
def comb(t,f): return f(t)
print comb(10, f1)
print comb(10, f2)

Related

Integrating a function of two variables over an array of values

I'm currently trying to solve this integral using SciPy:
I was first advised to use interpolation, which I tried but cannot figure out for some reason, but would probably be a good approach. I found this post about using np.vectorize and I think it might still work, but I am getting an error. Here is the code that I have written thus far (also note that n and n,eq are not indices, they're just variable names):
import numpy as np
from scipy import integrate
def K(x): #This is a function in the integral.
b = 0.252
return b*(((4/(x**3))+(3/(x**2))+1/x) + (4/(x**3) + 1/(x**2))*np.exp(-x))
def Xntot_integrand(x,z): #Defining the integrand
Xneq_x = (1+np.exp(x))**(-1) #This is the term outside the integral and squared within it.
return Xneq_x(x)**2 * np.exp(K(z) - K(x)) * np.exp(x)
Xntot_integrand = np.vectorize(Xntot_integrand)
def Xntot_integrated(x,z):
return quad(Xntot_integrand, 0, z)
Xntot_integrated=np.vectorize(Xntot_integrated)
T_narrow = np.linspace(1,0.01,100) #Narrow T range from 1 to 0.01 MeV
z_narrow = Q/T_narrow
final_integrated_Xneq = Xntot_integrated(z_narrow)
I am getting the error that I am missing a positional argument when I call Xntot_integrated (which makes sense, I think it is still in the two variables x and z).
So I suppose the issue is stemming from where I use quad() because after it is integrated, x should go away. Any advice? Should I use tabulation/interpolation instead?
You need to be using the args keyword argument of integrate.quad to pass additional inputs to the function, so it would look like this:
def Xntot_integrated(z):
return integrate.quad(Xntot_integrand, 0, z, args=(z,))
Note here x is not an input to the integrated function, only z, the first input to the integrand is the integration variable and any extra information is passed via args=(z,) tuple.
alternatively you can define a wrapper that knows z from context and only takes the integration variable as input:
def Xntot_integrated(z):
def integrand(x):return Xntot_integrand(x,z)
return integrate.quad(integrand, 0, z)
but most API's that take a function typically have a keyword argument to specify those inputs. (threading.Thread comes to mind.)
also your Xneq_x should probably be a function itself since you accidentally use it as such inside your integrand (it is just a value there right now) and you will need to use it outside the integration anyway :)

Python Fastest Way to Remove N-Rightmost Number From Integer

What is the fastest way to remove the N-Rightmost number in python integer?
Here are some of my code:
def f_int(dividend,n):
return int(dividend/(10 ** n))
def f_str_to_int(dividend,n):
return int(str(dividend)[:-n])
If we don't care whether the output is in str on int, we can skip the int() in def_f_str_to_int():
def f_str(dividend,n):
return str(dividend)[:-n]
We also can increase speed by asking the input in the form of power of ten:
divisor_in_power_of_ten = 10 ** n #outside function run time
def f_int_hack (dividend,divisor_in_power_of_ten):
return int(dividend/(divisor_in_power_of_ten))
My question is, is there a faster way (maybe using bit manipulation)? I need to optimize it since it will be used as part of a real-time web. Note: Restricted only using python, not JS or Cython (it's okay to extend your answer in JS and Cython, but that is not the main question).
Here is my result:
FUNCTION: f_int_hack Used 200170 times
MEDIAN 1.1000000004202093e-06
MEAN 1.5179877104460484e-06
STDEV 3.600025074234889e-05
FUNCTION: f_int Used 199722 times
MEDIAN 1.8999999999991246e-06
MEAN 2.420203582980709e-06
STDEV 3.482858342790541e-05
FUNCTION: f_str Used 200132 times
MEDIAN 1.4999999997655777e-06
MEAN 1.7462234924949252e-06
STDEV 1.4733864640549157e-05
FUNCTION: f_str_to_int Used 199639 times
MEDIAN 2.000000000279556e-06
MEAN 2.751038624717222e-06
STDEV 6.383386278143267e-05
Edit:
Function for the benchmark (edit accordingly, since I edit some of them):
import time
import random
import statistics
def benchmark(functions, iteration, *args):
times = {f.__name__: [] for f in functions}
for i in range(iteration):
func = random.choice(functions)
t0 = time.perf_counter()
func(*args)
t1 = time.perf_counter()
times[func.__name__].append(t1 - t0)
for name, numbers in times.items():
print('FUNCTION:', name, 'Used', len(numbers), 'times')
print('\tMEDIAN', statistics.median(numbers))
print('\tMEAN ', statistics.mean(numbers))
print('\tSTDEV ', statistics.stdev(numbers))
if __name__=="__main__":
# Variables
divident = 12345600000
n = 3
iteration = 1000000
# The functions to compare
def f_int(divident,n):
return int(divident/(10 ** n))
def f_str_to_int(divident,n):
return int(str(divident)[:-n])
functions = f_int, f_str_to_int
benchmark(functions, iteration, divident, n)
More clarification: input is python integer. Actually, i didn't care with the output format (wether it's str or int), but let's make the output in int first and str as "bonus question".
Edit:
From comment section a//b:
FUNCTION: f_int_double_slash Used 166028 times
MEDIAN 1.2000000002565514e-06
MEAN 1.4399938564575845e-06
STDEV 1.2767417156171526e-05
YES, IT'S FASTER THAN int(a/b)
Edit:
From comment, if we accept float, the fastest way is:
def f_float_hack(dividend,divisor_in_power_of_ten):
return dividend//divisor_in_power_of_ten
With result:
FUNCTION: f_float_hack Used 142983 times
MEDIAN 7.000000001866624e-07
MEAN 9.574040270508322e-07
STDEV 3.725603760159355e-05
Improvement of int double slash using precomputing power of ten:
FUNCTION: f_int_double_slash_hack Used 143082 times
MEDIAN 7.999999995789153e-07
MEAN 1.1596266476572136e-06
STDEV 4.9442788346866335e-05
Current result: float_hack is the fastest (if we accept float).

multiple functions as arguments in python

I have the following problem: I have two sets of data (set T and set F). And the following functions:
x(T) = arctan(T-c0), A(x(T)) = arctan(x(T) -c1),
B(x(T)) = arctan(x(T) -c2)
and Y(x(t),F) = ((A(x(t)) - B(x(t)))/2 - A(x(t))arctan(F-c3) + B(x(t))arctan(F-c4))
# where c0,c1,c2,c3,c4 are constants
Now I want to create a surface plot of Y. And for that I would like to implement Y as a python (numpy) function what turns out to be quite complicated, because Y takes other functions as input.
Another idea of mine was to evaluate x, B and A on the data separately and store the results in numpy arrays. With those I also could get the output of the function Y , but I don't know which way is better in order to plot the data and I really would like to know how to write Y as a python function.
Thank you very much for your help
It is absolutely possible to use functions as input parameters to other functions. A use case could look like:
def plus_one(standard_input_parameter_like_int):
return standard_input_parameter_like_int + 1
def apply_function(function_as_input, standard_input_parameter):
return function_as_input(standard_input_parameter)
if(__name__ == '__main__'):
print(apply_function(plus_one, 1))
I hope that helps to solve your specific problem.
[...] somethin like def s(x,y,z,*args,*args2): will yield an
error.
This is perfectly normal as (at least as far as I know) there is only one variable length non-keyword argument list allowed per function (that has to be exactly labeled as *args). So if you remove the asterisks (*) you should actually be able to run s properly.
Regarding your initial question you could do something like:
c = [0.2,-0.2,0,0,0,0]
def x(T):
return np.arctan(T-c[0])
def A(xfunc,T):
return np.arctan(xfunc(T) - c[1])
def B(xfunc,T):
return np.arctan(xfunc(T) - c[2])
def Y(xfunc,Afunc,Bfunc,t,f):
return (Afunc(xfunc,t) - Bfunc(xfunc,t))/2.0 - Afunc(xfunc,t) * np.arctan(f - c[3]) + Bfunc(xfunc,t)*np.arctan(f-c[4])
_tSet = np.linspace(-1,1,20)
_fSet = np.arange(-1,1,20)
print Y(x,A,B,_tSet,_fSet)
As you can see (and probably already tested by yourself judging from your comment) you can use functions as arguments. And as long as you don't use any 'if' conditions or other non-vectorized functions in your 'sub'-functions the top-level function should already be vectorized.

How can i use a function with "variable" constants in scipy.optimize?

how can i use "variable" constants in scipy.optimize functions? I am trying to create an iterative optimisation algorithm, which updates certain parameters in the objective function after each optimisation run.
to use a very simple example of what i want to do:
from scipy import optimize as opt
def f(x, R):
return R * (x[0]**2 + x[1]**3)
R = 0.1 # initial R value
y = []
y.append([2,2]) # initial point
for i in range(0,10):
y.append(opt.fmin(f, y[i])) # how can i include 'R' in this line??
R = some_function_to_update_R(R)
any help would be appreciated
EDIT:
would it help to re-declare the objective function each time i optimise? so make the loop look like this instead?
for i in range(0,10):
def f_temp(x_temp):
return f(x_temp,R)
y.append(opt.fmin(f_temp, y[i]))
R = some_function_to_update_R(R)
or is there some better way?
fmin supports an optional args argument, representing a tuple of additional arguments to be passed to the function you're trying to optimize:
y.append(opt.fmin(f, y[i], args=(R,)))
This is explained in the documentation for fmin; you should get into the habit of checking the documentation when you want to figure out how to do something.

Python -- nondimensionalize

I'm writing a python module to allow me to make unit-based calculations, and I'm trying to implement unit-sensitive integration of functions. My idea is basically to write a wrapper for scipy.integrate -- take the function and arguments given, including the limits of integration, nondimensionalize them all, pass to scipy.integrate.quad or some such thing, get the answer, and then multiply by the correct units at the end.
To accomplish this, I'm trying to figure out how to nondimensionalize an arbitrary function. I've implemented units so that if you divide two quantities with the same units, it returns an ordinary number, so my first thought was to just do this:
def nonDimensionalize(func, *args):
val = func(*args)
dimensions = val / val.value
return lambda args : (func(args) / dimensions)
This works like a charm to nondimensionalize the function's output, but I'm having a harder time with the input. What I really need is to return a function that takes in ordinary numbers, multiplies them by the correct SI dimensions (which I can figure out how to do), gets the output, divides it by the correct SI dimensions, and returns that value as an ordinary number. Then I can pass said function to scipy.integrate (or scipy.fslove, etc.). I tried the following:
def nonDimensionalize(func, *args):
argDims = []
for arg in args:
aDim = arg / arg.value
argDims.append(aDim)
nDargs = []
index = 0
for arg in args:
nDargs.append(arg / argDims[index])
index += 1
val = func(*args)
dimensions = val / val.value
return lambda args : (func(args) / dimensions)
but it doesn't work; it has exactly the same effect as my four-line function above. I'm not sure how to proceed at this point. Help?
What I really need is to return a function that takes in ordinary numbers, multiplies them by the correct SI dimensions (which I can figure out how to do), gets the output, divides it by the correct SI dimensions, and returns that value as an ordinary number.
I'm not sure I understand exactly how you dimensionalize/non-dimensionalize values, so just modify the corresponding functions as necessary, but you could do it like this:
def dimensionalizeValue(nonDimValue, dimensions):
return nonDimValue * dimensions
def nonDimensionalizeValue(dimValue):
dimensions = dimValue / dimValue.value
return dimValue / dimensions
def nonDimensionalizeFunction(function):
def wrapper(*nonDimArgs):
# Figure out the correct dimensions.
dimensions = None
# Transform/dimensionalize the arguments.
dimArgs = [dimensionalizeValue(arg, dimensions) for arg in nonDimArgs]
# Get output using dimensionalized arguments.
dimVal = function(*dimArgs)
# Non-dimensionalize the output.
nonDimVal = nonDimensionalizeValue(dimVal)
return nonDimVal
return wrapper

Categories

Resources