Home > Blockchain >  Calculations between 2 numpy arrays
Calculations between 2 numpy arrays

Time:06-05

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)
  • Related