Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Comparing all elements of two arrays and modifying 2nd array

New to Python, and have been learning about arrays. I am stuck with a simple enough problem and need a solution. I have two arrays:

a = [2.0, 5.1, 6.2, 7.9, 23.0]     # always increasing
b = [5.1, 5.5, 5.7, 6.2, 00.0]     # also always increasing

and I want the resultant array to be:

c = [0.0, 5.1, 6.2, 0.0, 0.0]      # 5.5, 5.7, 00.0 from 'b' were dropped and rearranged such that position of equivalent elements as in 'a' are maintained

I have compared both 'a' & 'b' using Numpy as in:

y = np.isclose(a, b)
print y
# [False False False False False]

(Alternately,) I also tried something like this, which isn't the right way (I think):

c = np.zeros(len(a))
for i in range (len(a)):
    for j in range (len(a)):
        err = abs(a[i]-b[j])
        if err == 0.0 or err < abs(1):
            print (err, a[i], b[j], i, j)
        else:
            print (err, a[i], b[j], i, j)

How do I proceed from here towards obtaining 'c'?

like image 415
rNov Avatar asked Apr 15 '26 02:04

rNov


2 Answers

These solutions work even when the arrays are of different size.

Simple version

c = []

for i in a:
    if any(np.isclose(i, b)):
        c.append(i)
    else:
        c.append(0.0)

Numpy version

aa = np.tile(a, (len(b), 1))
bb = np.tile(b, (len(a), 1))
cc = np.isclose(aa, bb.T)
np.any(cc, 0)
c = np.zeros(shape=a.shape)
result = np.where(np.any(cc, 0), a, c)

Explained:

I will be doing matrix comparison here. First you expand the arrays into matrices. Lengths are exchanged, which creates matrices having equal size of one dimension:

aa = np.tile(a, (len(b), 1))
bb = np.tile(b, (len(a), 1))

They look like this:

# aa
array([[  2. ,   5.1,   6.2,   7.9,  23. ],
       [  2. ,   5.1,   6.2,   7.9,  23. ],
       [  2. ,   5.1,   6.2,   7.9,  23. ],
       [  2. ,   5.1,   6.2,   7.9,  23. ],
       [  2. ,   5.1,   6.2,   7.9,  23. ]])

# bb
array([[ 5.1,  5.5,  5.7,  6.2,  0. ],
       [ 5.1,  5.5,  5.7,  6.2,  0. ],
       [ 5.1,  5.5,  5.7,  6.2,  0. ],
       [ 5.1,  5.5,  5.7,  6.2,  0. ],
       [ 5.1,  5.5,  5.7,  6.2,  0. ]])

Then compare them. Note that bb is transposed:

cc = np.isclose(aa, bb.T)

And you get:

array([[False,  True, False, False, False],
       [False, False, False, False, False],
       [False, False, False, False, False],
       [False, False,  True, False, False],
       [False, False, False, False, False]], dtype=bool)

You can aggregate this by axis 0:

np.any(cc, 0)

which returns

array([False,  True,  True, False, False], dtype=bool)

Now create array c:

c = np.zeros(shape=a.shape)

And select appropriate value, either from a or c:

np.where(np.any(cc, 0), a, c)

And the result:

array([ 0. ,  5.1,  6.2,  0. ,  0. ])
like image 108
hruske Avatar answered Apr 17 '26 14:04

hruske


With np.isclose you already create an array where the "closest" elements are True. So you can use this result to set all other elements to zero.

import numpy as np
a = np.array([2.0, 5.1, 6.2, 7.9, 23.0])     # always increasing
b = np.array([5.1, 5.5, 5.7, 6.2, 00.0])     # also always increasing
a[~np.isclose(a,b, atol=0.5)] = 0
a

this returns array([ 0. , 5.1, 6.2, 0. , 0. ]).

But notice you want to set all elements that are not close, so you need to invert (~) the result.

like image 39
MSeifert Avatar answered Apr 17 '26 14:04

MSeifert



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!