Assume a simple 1-dimensional numpy array:
>>> x = np.array([1,3,5,0,3,2])
Now assume I want to perform the operation 1.0/x. I can do this with numpy:
>>> 1.0/x
array([ 1. , 0.33333333, 0.2 , inf, 0.33333333,
0.5 ])
The problem here is the infinity (inf) result for the original element value 0, because 1.0/0 seems to return infinity in place of undefined behaviour.
Instead of infinity, I would like to provide my own custom value where these divide by 0 scenarios arise. While I know this can be accomplished using a loop, I would like to know whether there is any kind of idiomatic syntax for this kind of operation.
There's a related question here, but it only deals with the if something: (do this) else: (do nothing) scenario whereas my question is a if something: (do this) else: (do that) scenario.
You can always patch it up later:
a = 1.0/x
inf_ind = np.isinf(a)
a[inf_ind] = your_value
or
a[inf_ind] = f(x[inf_ind])
Which has the advantage of not getting in the way of the nice optimized numpy methods.
Building on the previous answer, you can also set floating point callback modes to detect when you need to apply the inf transform.
I can't find a callback that gets called on each floating point error, however.
See also:
http://docs.scipy.org/doc/numpy/reference/generated/numpy.seterr.html
import numpy
class IsDivideError(object):
def __init__(self):
self.hasDivideError=False
def callback(self, x,y):
self.hasDivideError=True
ide=IsDivideError()
numpy.seterr(divide='call')
numpy.seterrcall(lambda x,y: ide.callback(x,y) )
x = numpy.array([1,3,5,0,3,2])
val=1.0/x
if(ide.hasDivideError):
val[numpy.isinf(val)]=5
Related
I am trying to implement a calculation from a research paper. In that calculation, the value of a function is supposed to be
0, for x<a
sqrt(x-a)*SOMETHING_ELSE, for x>=a
In my module, x and a are 1D numpy-arrays (of the same length). In my first attempt I implemented the function as
f = np.sqrt(x-a)*SOMETHING*np.heaviside(x,a)
But for x<a, np.sqrt() returns NaN and even though the heaviside function returns 0 in that case, in Python 0*NaN = NaN.
I could also replace all NaN in my resulting array with 0s afterwards but that would lead to warning outputs from numpy.sqrt() used on negative values that I would need to supress. Another solution is to treat the argument of the squareroot as an imaginary number by adding 0j and taking the real part afterwards:
f = np.real(np.sqrt(x-a+0j)*SOMETHING*np.heaviside(x,a))
But I feel like both solutions are not really elegant and the second solution is unnecessarily complicated to read. Is there a more elegant way to do this in Python that I am missing here?
You can cheat with np.maximum in this case to not compute the square root of negative numbers.
Moreover, please note that np.heaviside does not use a as a threshold but 0 (the second parameter is the output of the heaviside in some case). You can use np.where instead.
Here is an example:
f = np.where(x<a, 0, np.sqrt(np.maximum(x-a, 0))*SOMETHING)
Note that in this specific case, the expression can be simplified and np.where is not even needed (because np.sqrt(np.maximum(x-a, 0)) gives 0). Thus, you can simply write:
f = np.sqrt(np.maximum(x-a, 0))*SOMETHING
I want to multiply two numeric numpy objects t and speed without knowing a-priori whether each one is scalar or an array. The problem is that 0 is a legal value for t (or for elements of t), and inf is a legal value for speed (or for elements of speed). The model I'm working with has a rule for this case: wherever speed is infinite and t is zero, the product is defined as 0.
My problem is in applying the rule while coping with the possibly-scalar-possibly-not-ness of both operands. So far the best I can come up with is this ugly cascade:
if t.size == 1:
if t.flat[0]:
t = t * speed
else:
nonzero = t != 0
if speed.size == 1:
t[nonzero] *= speed
else:
t[nonzero] *= speed[nonzero]
I can't help but think there has to be a more efficient, more Numpythonic way that I'm missing. Is there?
0 * np.inf throws a RuntimeWarning and evaluates to np.nan
How about just doing the multiplication, and replacing the np.nan after that?
import numpy as np
def multiply(a, b):
temp = np.array(a*b)
temp[np.isnan(temp)] = 0
return temp
Testing:
np.random.seed(123)
t = np.random.rand(10)
t[0] = 0
speed = np.random.rand(10)
speed[0] = np.inf
speed[6] = np.inf
input:
multiply(t, speed)
output:
array([ 0. , 0.09201602, 0.02440781, 0.49796297, 0.06170694,
0.57372377, inf, 0.03658583, 0.53141369, 0.1746193 ])
It's been a couple of days, and nobody has written up the answer given in comments by hpaulj and SubhaneilLahiri, so I had better do it myself. My reason for making this the accepted answer is that it is general enough to address the question's title, even in cases that go beyond the specific model given in the question.
# prepare zeros of the correct shape:
out = np.zeros(np.broadcast(t, speed).shape), dtype=float)
# write the product values into the prepared array, but ONLY
# according to the mask t!=0
np.multiply(t, speed, where=t!=0, out=out)
In the particular model in the question, the pre-prepared default output value of 0 is already correct for all places where the test t!=0 fails: 0 * speed is 0 anyway wherever speed is finite, and it is also 0 by fiat (according to the model's rule) when speed is infinite. But this approach is adaptable to the more general case: in principle, it would be possible to use additional numpy ufunc calls to fill in the masked-out parts of the output array with the results of arbitrarily different rules.
Have an equation where I cannot get the variable I want to solve for onto only one side. I want to solve for that variable for given values of all the other variables in the equation.
For a simple example as clarification, suppose you couldn't get x onto only one side of the following equation even though you can:
sqrt(x)=(a/13)*log(b/x^2)
Since you can't get it onto one side, you can't define x as an expression - how would you solve for x (with given values of a and b) when x is an undefined variable?
General procedure: Move everything to the left side of the = so you get stuff = 0. Replace all other variables with given values. Make any simplifications possible, like replace 2.37 * 3.3 with 7.821. You now have an expression with one unknown variable. Example: exp(x) + 2.7*sin(x) -33. Make this into a function, with any necessary imports.
from math import exp, sin
def f(x):
return exp(x) + 2.7*sin(x) -33
Now look for a value of x that makes f(x) = 0. Start by finding 2 values that make f both less and greater than 0.
>>> f(3)
-12.533439055050689
>>> f(4)
19.554783295812832
At this point, you can use a bracketing root finder (scipy must have one) with 3 and 4 as the initial guesses, or continue by hand. I would try 3.5 next, and then 3.25 or 3.75 depending on the sign of f(3.5). As an exercise, you could write a function yourself that automates the binary search.
You can use gradient descent tools to solve it. Look here where they use tensorflow (maybe too much for the example but it is not bad to learn anyway): https://medium.com/#liccowee/tensorflow-to-solve-simple-math-equation-27f42a44f0f1
I am newbie in Python. I think I'm looking for something easy, but can't find.
I have an numpy binary array, e.g.:
[1,0,1,1,0,0,0,1,1,1,1,0]
And I want to do 2 things:
Join (?) all elements into one number, so result will be:
x=101100011110
Next want to converse it into binary, so:
xx=2846
I have an algorithm to do 2., but I don't know how to do 1. I can do it using loop, but is it possible to do it using numpy, without loop? My array will be huge, so I need the best option.
>>> int(''.join(map(str, [1,0,1,1,0,0,0,1,1,1,1,0])))
101100011110
Or with a little numpy:
>>> int(''.join(np.array([1,0,1,1,0,0,0,1,1,1,1,0]).astype('|S1')))
101100011110
I like #timgeb's answer, but if you're sure you want to use numpy calculations directly, you could do something like this:
x = np.array([1,0,1,1,0,0,0,1,1,1,1,0])
exponents = np.arange(len(x))[::-1]
powers = 10**exponents
result = sum(powers * x)
In [12]: result
Out[12]: 101100011110
As pointed out by #Magellan88 in the comments, if you set powers=2**exponents you can get from 0 to your second part of the question in one sweep.
Since you don't want loop in first task then you can go with map method , I just wanted to show you can also try this :
import numpy as np
array=np.array([1,0,1,1,0,0,0,1,1,1,1,0])
int_con=str(array).replace(',','').replace(' ','').replace('[','').replace(']','')
print("Joined {}".format(int_con))
bin_to_de=0
for digit in int_con:
bin_to_de=bin_to_de*2+int(digit)
print("Decimal conversion {}".format(bin_to_de))
output:
Joined 101100011110
Decimal conversion 2846
I would like to propagate uncertainty using python. This is relatively easy for simple functions via the uncertainties package. However, it is not that obvious to achieve the same with a user defined function. What follows is an example of what I am trying to do.
import mcerp as err
import numpy as np
def mult_func(x,xm ,a):
x[x==0.] = 1e-20
v = (1.-(xm/x)**a) * (x > xm)
v[np.isnan(v)] = 0.
return v
def intg(e,f,cut,s):
t = mult_func(e,cut,s)
res = np.trapz(t*f,e)
return res
x=np.linspace(0,1,10000)
y=np.exp(x)
m=0.
mm=0.
N=100000
for i in range(0,N):
cut=np.random.normal(0.21,0.02)
stg=np.random.normal(1.1,0.1)
v=intg(x,y,cut,stg)
m=m+v
mm=mm+v*v
print("avg. %10.5E +/- %10.5E fixed %10.5E"%(m/N,np.sqrt((mm/N-(m/N)**2)),intg(x,y,0.21,1.1)))
What is done above is just random sampling of two parameters and calculating the mean and the variance. I am not sure however, how much this brute-force method is adequate. I could use the law of large numbers and to try estimate how many trials N are needed to get a certain value (P=1-1/(N*k**2)) to be around k times standard deviations around the true mean.
In principle what I wrote could work. However, my assumption is that being such a flexible language with many powerful packages, python could do this task much more effectively. I was thinking about uncertainties, mcerp and pymc. Due to my limited experience using those packages, I am not sure how to proceed.
EDIT:
MY original example was not that much informative, this is why I decided to do a new example which actually works to illustrate my idea.
Numpy supports arrays of arbitrary numeric types. However, not all functions are supporter for arbitrary numeric types.
In this case, both numpy.exp and trapz are not supported.
Note that the uncertanties module contains the unumpy package. numpy.exp has a replacement here: uncertainties.unumpy.exp
We, define trapz as a ufunc.
Check it out here!
a=un.ufloat(0.3,0.01)
b=un.ufloat(1.2,0.071)
def sample_func(a: un.UFloat, b: un.UFloat) -> np.ndarray:
x=np.linspace(0,a,100)
y = un.unumpy.exp(x)
return utrapz(y, x)
def utrapz(y: np.ndarray, x: np.ndarray) -> np.ndarray:
Δx = x[1:]-x[:-1]
avg_y = (y[1:]+y[:-1])/2
return (Δx*avg_y)
print(sample_func(a, b))
OUT:
[0.00026601240063021264+/-nan 0.0005935120815465686+/-6.429403852670308e-06
0.0006973604419223405+/-3.888235103342809e-06 ...,
0.002095505706899622+/-6.503985178118233e-05
0.0021019968633076134+/-6.545802781649068e-05
0.0021084415802710295+/-6.587387316821736e-05]