2

I have two arrays, A and B. Based on a function, I create a subset C from A and a subset D from B. Now, I want to join them together ( I want to keep those items that are in C and D with the same index in A and B).

A = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20])
B = np.array([20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1])
C = np.array([3,7,13])
D = np.array([18,8])

fvl1 = list()
fvl2 = list()


for i in C:
    index = np.where(A == i)
    if B[index] in D:
        fvl1.append(A[index])
        fvl2.append(B[index])

print(fvl1)
print(fvl2)

Output:
[array([3]), array([13])]
[array([18]), array([8])]

This is what I've done until now, but it's really slow. Is there any way to optimize this for it to go faster?

LE: You can see that the element 3 in A has the same index as element 18 in B(index = 3), same with element 13 from A and 8 from B.

4
  • 1
    Have you tried using sets instead of lists? Commented Nov 27, 2017 at 22:06
  • MCVE please.... Commented Nov 27, 2017 at 22:08
  • 1
    edited example now Commented Nov 27, 2017 at 22:17
  • Is A always sorted? Commented Nov 27, 2017 at 22:25

2 Answers 2

3

You could use np.ind1d or np.isin:

Returns a boolean array of the same shape as element that is True where an element of element is in test_elements and False otherwise.

>>> import numpy as np
>>> A = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20])
>>> B = np.array([20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1])
>>> C = np.array([3,7,13])
>>> D = np.array([18,8])
>>> np.in1d(A, C) & np.in1d(B, D)
array([False, False,  True, False, False, False, False, False, False,
       False, False, False,  True, False, False, False, False, False,
       False, False], dtype=bool)
>>> indices = np.isin(A, C) & np.isin(B, D)
>>> A[indices]
array([ 3, 13])
>>> B[indices]
array([18,  8])

It's not clear if C and D are converted to sets, but I suppose it will be faster than your current code.

Sign up to request clarification or add additional context in comments.

Comments

1

I'm not 100% sure I interpreted your question correctly, but a combination of zip and list comprehension might be what you're after.

fv = [(a, b) for (a, b) in zip(A, B)
      if <condition for first list>
      and <condition for second list>]

fv1 = [t[0] for t in fv]
fv2 = [t[1] for t in fv]

zip joins your lists together into a list of tuples.

list(zip([1, 2, 3],['a','b','c'])) == [(1,'a'),(2,'b'),(3,'c')]

You can then filter which outputs you want with conditions in your list comprehension. For example:

fv = [(a, b) for (a, b) in zip(range(10),'abcdefghijklmnop') 
      if a%2 
      and b>'d']
[(5, 'f'), (7, 'h'), (9, 'j')]

Your case can actually be done as a one liner:

fv1, fv2 = zip(*((a, b) for (a, b) in zip(A, B) if a in C and b in D))
fv1 #(3, 13)
fv2 #(18, 8)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.