2

I have an array arorg like this:

import numpy as np
arorg = np.array([[-1., 2., -4.], [0.5, -1.5, 3]])

and another array values that looks as follows:

values = np.array([1., 0., 2.])

values has the same number of entries as arorg has columns.

Now I want to apply functions to the entries or arorg depending on whether they are positive or negative:

def neg_fun(val1, val2):
    return val1 / (val1 + abs(val2))

def pos_fun(val1, val2):
    return 1. / ((val1 / val2) + 1.)

Thereby, val2 is the (absolute) value in arorg and val1 - this is the tricky part - comes from values; if I apply pos_fun and neg_fun to column i in arorg, val1 should be values[i].

I currently implement that as follows:

ar = arorg.copy()

for (x, y) in zip(*np.where(ar > 0)):
    ar.itemset((x, y), pos_fun(values[y], ar.item(x, y)))

for (x, y) in zip(*np.where(ar < 0)):
    ar.itemset((x, y), neg_fun(values[y], ar.item(x, y)))

which gives me the desired output:

array([[ 0.5       ,  1.        ,  0.33333333],
       [ 0.33333333,  0.        ,  0.6       ]])

As I have to do these calculations very often, I am wondering whether there is a more efficient way of doing this. Something like

np.where(arorg > 0, pos_fun(xxxx), arorg)

would be great but I don't know how to pass the arguments correctly (the xxx). Any suggestions?

7
  • For the [0,0] item of the returned value, should the answer be inf? arorg[0,0] is negative, so we apply neg_fun, which has a denominator of 0. val1 / (val1 + val2) = 1. / (1. - 1.) Commented Apr 26, 2017 at 12:19
  • @James: arorg[0, 0] is -1, so we indeed apply neg_fun; values[0] is 1.. Then we would get: 1. / (1. + abs(-1)) = 0.5. Where do you see the inf? Commented Apr 26, 2017 at 12:24
  • Also for [0,3] item, should the result be -1 (2/(-4+2))? Commented Apr 26, 2017 at 12:24
  • You didn't include the abs in your function Commented Apr 26, 2017 at 12:24
  • in your func def, there is no abs() Commented Apr 26, 2017 at 12:25

3 Answers 3

2

As hinted in the question, here's one using np.where.

First off, we are using a direct translation of the function implementation to generate values/arrays for both positive and negative cases. Then, with a mask of positive values, we will choose between those two arrays using np.where.

Thus, the implementation would look something along these lines -

# Get positive and negative values for all elements
val1 = values
val2 = arorg
neg_vals = val1 / (val1 + np.abs(val2))
pos_vals = 1. / ((val1 / val2) + 1.)

# Get a positive mask and choose between positive and negative values 
pos_mask = arorg > 0
out = np.where(pos_mask, pos_vals, neg_vals)
Sign up to request clarification or add additional context in comments.

Comments

1

You don't need to apply function to zipped elements of arrays, you can accomplish the same thing through simple array operations and slicing.

First, get the positive and negative calculation, saved as arrays. Then create a return array of zeros (just as a default value), and populate it using boolean slices of pos and neg:

import numpy as np
arorg = np.array([[-1., 2., -4.], [0.5, -1.5, 3]])
values = np.array([1., 0., 2.])

pos = 1. / ((values / arorg) + 1)
neg = values / (values + np.abs(arorg))

ret = np.zeros_like(arorg)
ret[arorg>0] = pos[arorg>0]
ret[arorg<=0] = neg[arorg<=0]

ret
# returns:
array([[ 0.5       ,  1.        ,  0.33333333],
       [ 0.33333333,  0.        ,  0.6       ]])

Comments

1
import numpy as np
arorg = np.array([[-1., 2., -4.], [0.5, -1.5, 3]])
values = np.array([1., 0., 2.])
p = 1.0/(values/arorg+1)
n = values/(values+abs(arorg))
#using np.place to extract negative values and put them to p
np.place(p,arorg<0,n[arorg<0])
print(p)
[[ 0.5         1.          0.33333333]
 [ 0.33333333  0.          0.6       ]]

1 Comment

Works fine, thanks (upvoted)! Just a minor thing: a is not defined, that should be arorg.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.