Apply function into arr and print out

Viewed 66
def kiem_tra_so_hoan_chinh(so):
    if so <= 1:
        return False
    else:
        tong = 0
        for i in range(1, so):
            if so % i == 0:
                tong += i
        if tong == so:
            return True
        else:
            return False

         
        np.random.seed(5)
    arr1 = np.random.randint(low = 1, high = 101, size = 16) 
    arr1=arr1.reshape(4,4)
    arr1

How can I use the function into array and print out arr1 line if it contains perfect number If I use kiem_tra_so_hoan_chinh(arr1), it shows an error:

"ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()"

2 Answers

Something like this using list comprehension should do the trick.

def kiem_tra_so_hoan_chinh(so):
    if so <= 1:
        return False
    else:
        tong = 0
        for i in range(1, so):
            if so % i == 0:
                tong += i
        if tong == so:
            return True
        else:
            return False
    
np.random.seed(5)
arr1 = np.random.randint(low = 1, high = 101, size = 16) 
# use iterator to apply function to each element
is_perfect = np.array([kiem_tra_so_hoan_chinh(i) for i in arr1])
is_perfect_reshaped=is_perfect.reshape(4,4)
# each element is now a row of 4, so apply sum(row)>0 to find
# at least one perfect number.
contains_perfect = np.array([sum(row)>0 for row in is_perfect_reshaped])
print(arr1.reshape(4,4))
print(is_perfect_reshaped)
print(contains_perfect)

[[100  79  62  17]
 [ 74   9  63  28]
 [ 31  81   8  77]
 [ 16  54  81  28]]
[[False False False False]
 [False False False  True]
 [False False False False]
 [False False False  True]]
[False  True False  True]

Method 1:

Use np.vectorize and any with list comprehension. Note: np.vectorize is just a fancy numpy for-loop

arr2 = arr1[[np.vectorize(kiem_tra_so_hoan_chinh)(i).any() for i in arr1],:]

Out[533]:
array([[74,  9, 63, 28],
       [16, 54, 81, 28]])

Method 2:

np.vectorize with np.apply_along_axis:

arr2 = arr1[np.apply_along_axis(np.vectorize(kiem_tra_so_hoan_chinh), 1, arr1)
              .any(1),:]

Out[540]:
array([[74,  9, 63, 28],
       [16, 54, 81, 28]])

Method 3:

np.frompyfunc with list comprehension:

arr2 = arr1[[np.frompyfunc(kiem_tra_so_hoan_chinh,1,1)(i).any() for i in arr1],:]

Out[545]:
array([[74,  9, 63, 28],
       [16, 54, 81, 28]])
Related