I'm writing a program that does calculations on 2 numpy arrays, but the calculations are performed only on elements not less than 4
, for example:
Input:
array1 = np.array([[4, 4, 6], [2, 3, 9]])
array2 = np.array([1, 1, 2])
Output:
([5, 9])
Explanation:
For the first element, the calculation is (4*1 4*1 6*2) / (1 1 2) = 5
For the second element, the calculation is (9*2) / 2 = 9 (because 2 and 3 are less than 4)
So, I've tried to convert the numbers that are less than 4
into 0
for the numerator:
def function(array1, array2):
return np.sum(np.where(array1 >= 4, array1 * array2, 0), axis=1)
But for the denominator, I don't know how to convert the numbers into 0
if the elements in array1
are less than 4
. Can anyone help me with this problem? Thanks for your help !
CodePudding user response:
You may need to make array2 the same size as array1:
>>> array1 = np.array([[4, 4, 6], [2, 3, 9]])
>>> array2 = np.array([1, 1, 2])
>>> array2 = array2 * (array1 >= 4)
>>> array2
array([[1, 1, 2],
[0, 0, 2]])
>>> (array1 * array2).sum(-1) / array2.sum(-1)
array([5., 9.])
CodePudding user response:
You have to calculate the denominator same way you calculate the numerator.
One thing to pay attention to is division by 0 (your input data doesn't trigger that situation, but I added some that does).
Here's an example (I'm sure there are faster (and better) ways to accomplish this).
code00.py:
#!/usr/bin/env python
import sys
import numpy as np
def divide(a0, a1):
num = np.sum(np.where(a0 >= 4, a0 * a1, 0), axis=1)
#print("num:", num)
denom = np.sum(np.where(a0 >= 4, a1, 0), axis=1)
#print("denom:", denom)
errs = np.geterr()
np.seterr(invalid="ignore")
ret = np.where(denom == 0, 0, num / denom) # A warning will pop up even if no division by 0 is actually performed
if errs["invalid"] != "ignore":
np.seterr(invalid=errs["invalid"])
return ret
def main(*argv):
test_sets = (
(
((4, 4, 6), (2, 3, 9)),
(1, 1, 2),
),
(
((4, 1, 4), (1, 1, 2)), # 2nd element will yield 0 for both numerator and denominator
(1, 1, 2),
),
)
for test_set in test_sets:
arrs = [np.array(e) for e in test_set]
print(divide(*arrs))
if __name__ == "__main__":
print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
64 if sys.maxsize > 0x100000000 else 32, sys.platform))
rc = main(*sys.argv[1:])
print("\nDone.")
sys.exit(rc)
Output:
[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q072504478]> "e:\Work\Dev\VEnvs\py_pc064_03.09_test0\Scripts\python.exe" ./code00.py Python 3.9.9 (tags/v3.9.9:ccb0e6a, Nov 15 2021, 18:08:50) [MSC v.1929 64 bit (AMD64)] 064bit on win32 [5. 9.] [4. 0.] Done.
CodePudding user response:
import numpy as np
array1 = np.array([[4, 4, 6], [2, 3, 9]])
array2 = np.array([1, 1, 2])
array1_consider = np.where(array1<4,0,1)
array2 = array1_consider*array2
nominator = np.sum(array1*array2,axis=1)
denominator = np.sum(array2,axis=1)
result = nominator/denominator
print(result)
CodePudding user response:
You can mask your data with where
, then compute a dot product. For your denominator, use the mask to broadcast the factors per row, than sum
and divide:
mask = array1>=4
b = np.where(mask, array1, 0)
# array([[4, 4, 6],
# [0, 0, 9]])
d = (array2*mask).sum(1)
# array([4, 2])
(b@array2)/d
# array([5., 9.])
In two lines:
mask = array1>=4
out = np.where(mask, array1, 0)@array2/(array2*mask).sum(1)