1

Numpy allows to pass a numpy.array as argument into a function and evaluate the function for every element of the array.:

def f(n):
    return n**2

arr = np.array([1,2,3])
f(arr)

outputs:

>>>[1 4 9]

This works fine, as long as f(n)doesn't perform boolean operations on n like this:

def f(n):
    if n%2 == 0:
        print(n)

The above code throws following exception: ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

This makes sense since the debugger showed, that the function f(n) received the entire numpy.arrayas input. Now, I'm looking for a way to change the code behaviour, so that I can perform boolean operations on the inputs. Is this possible while passing the entire numpy.array, or do I have to call the function by manually iterating over each element of the array?

---Edit:---

def get_far_field_directivity(k,a,theta):
    temp = k*a*np.sin(theta)
    if temp == 0: return 1
    else: return (2*sp.jn(1,(temp)))/(temp)

The function returns to other functions, which have to use its value on further calculation which is why the indexing approach by @Chrysophylaxs won't work.

Mr.X
  • 97
  • 1
  • 12
  • ^ is bitwise XOR, so you are just doing this arr^2, and it outputs `array([3, 0, 1], dtype=int32)` is that what you want? – Alex L Nov 05 '22 at 17:05
  • Unfortunately, I didn't mean that. This isn't the actual piece of code, I'm working on, so I didn't notice. I meant to square it - Sorry :-( – Mr.X Nov 05 '22 at 17:09
  • Well, what behavior do you want? Print every element where the condition is true? – Homer512 Nov 05 '22 at 17:14
  • Yes, that's what I want. This is just a minimal working example. So this might seem kind of useless. – Mr.X Nov 05 '22 at 17:23
  • I think it would help to clarify your requirements. Are you specifically wanting to call `f()` for each element in the array, or is the function `f()` just part of a solution you aren't getting to work quite right? – sj95126 Nov 05 '22 at 17:25
  • I've just clarified the question. I have to call `f()`on every single element. – Mr.X Nov 05 '22 at 17:30
  • This may help then: [Most efficient way to map function over numpy array](https://stackoverflow.com/q/35215161/13843268). – sj95126 Nov 05 '22 at 17:35
  • This would work however, I'm trying to avoid this solution, since in the real application, I have 3 Arrays with x,y,z Coorinates and passing the `np.arrays`, which actually are a meshgrid could get quite hairy and unelegant. – Mr.X Nov 05 '22 at 17:43
  • The basic problem is that an array, or condition on an array, cannot be used in an `if`. `if` is a simple True/False branch. It does not do any sort of iteration. You have to do the iteration yourself, e.g. `for x in y: if x>0: do something`. There are many, many, SO about this `ambiguity` error. – hpaulj Nov 05 '22 at 17:53

2 Answers2

1

do you want to try something like this? https://numpy.org/doc/stable/reference/generated/numpy.vectorize.html

import numpy as np

arr = np.array([1,2,3])

def f(n):
    if n%2 == 0:
        print(n)
    return n**2

vfunc = np.vectorize(f)      
vfunc(arr)          

outputs:

2
array([1, 4, 9])

whereas this

f(arr)     

outputs:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in f
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Alex L
  • 4,168
  • 1
  • 9
  • 24
0

Your second example step by step with input np.array([1, 2, 3, 4, 5]):

  • First n%2 is executed, which returns np.array([1, 0, 1, 0, 1]), which is the elementwise modulo 2.
  • Next, the resulting array is elementwise compared to 0, which results in: np.array([False, True, False, True, False]).
  • Finally, this array is checked for truthyness in the if statement. That is where the problem occurs, because the array contains multiple elements, and numpy can't be sure whether you intend this to be True or False.

I suspect that instead you want to print all of the values in the input array whose modulo 2 equals 0. If that is the case, you can do that by filtering those out by indexing using the boolean array:

def f(n):
    evens = n[ n%2 == 0 ]
    print(evens)
Input:   f(np.array([1, 2, 3, 4, 5]))
Output:  array([2, 4])
Chrysophylaxs
  • 5,818
  • 3
  • 10
  • 21
  • Unfortunately this won't work, since I have to return a value in the condition. If the condition is not met, I return another value. The above code is just a minimal working example, but I will add the actual function in question. – Mr.X Nov 05 '22 at 17:26