1

I am attempting to match values of a 2d array with a list in order to create a new 2d array that contains the list and its corresponding values from the 2d array. Probably easier to understand in code than English...

import numpy as np

m_out = np.arange(50).reshape(25,2)
m_out_list = list(m_out[:,1])

eqn_out = range(7,17)

c_list = [(x,y) for x in eqn_out for y in m_out[:,0] if x in (m_out_list)]

print c_list

This code produces an answer I expect,

[(7, 0), (7, 2), (7, 4), (7, 6), ...

however it is not what I am attempting to accomplish. What I would like the last part of the list comprehension to do (or any other method that works) is to provide an array that matches the eqn_out list with it's corresponding unique original value; i.e

[(7,6), (9,8), (11,10), (13,12), (15,14), (17,16)]

I'm not sure how to do this exactly, any suggestions would be most appreciated.

2 Answers 2

3

[Edited to put the simpler approach first.]

In practice I'd probably just do:

In [166]: d = dict(m_out[:,::-1])
In [167]: [(k, d[k]) for k in eqn_out if k in d]
Out[167]: [(7, 6), (9, 8), (11, 10), (13, 12), (15, 14), (17, 16)]

But for fun, sticking in numpy, how about something like:

[Updated: better numpy method]:

In [15]: m_out[np.in1d(v, eqn_out)][:, ::-1]
Out[15]: 
array([[ 7,  6],
       [ 9,  8],
       [11, 10],
       [13, 12],
       [15, 14],
       [17, 16]])

Or my original numpy approach:

In [150]: import numpy as np
In [151]: m_out = np.arange(50).reshape(25,2)   
In [152]: v = m_out[:,1]    
In [153]: eqn_out = np.arange(7, 18)     
In [154]: eqn_out
Out[154]: array([ 7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17])

Keep only the values we know about:

In [155]: np.intersect1d(eqn_out, v)
Out[155]: array([ 7,  9, 11, 13, 15, 17])

Find where they're located at (assumes the data is sorted!!):

In [156]: v.searchsorted(np.intersect1d(eqn_out, v))
Out[156]: array([3, 4, 5, 6, 7, 8])

Use these indices for selection purposes:

In [157]: m_out[v.searchsorted(np.intersect1d(eqn_out, v))]
Out[157]: 
array([[ 6,  7],
       [ 8,  9],
       [10, 11],
       [12, 13],
       [14, 15],
       [16, 17]])

Flip:

In [158]: m_out[v.searchsorted(np.intersect1d(eqn_out, v))][:,::-1]
Out[158]: 
array([[ 7,  6],
       [ 9,  8],
       [11, 10],
       [13, 12],
       [15, 14],
       [17, 16]])
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for introducing the dictionary approach, that seems like it may work best for the larger context I am going to be working in. And thanks for the detailed numpy answer as well.
Be warned that the dictionary approach assumes that the numbers in m_out[:,1] are unique, so they make sense as dictionary keys. If that's true, then it should work well.
+1 for the use of np.in1d. The searchsorted and intersect1d are really overkill, though ;)
@PierreGM: ah, you know how it is. First you try something, it doesn't work, so you try something else you know will, and then you realize you almost had it right the first time. :^)
3

Something like that:

[(j, i) for (i,j) in m_out if j in eqn_out]

seems to work. However, it's probably a bit wasteful, as we're iterating on the whole m_out instead of a subset.

An alternative could be:

test = reduce(np.logical_or,v(m_out[:,1]==i for i in eqn_out))
[(j,i) for (i,j) in m_out[test]]

Here, we're iterating over len(eqn_out) boolean arrays, that we're combining in a single one with the reduce(np.logical_or, ...). We use this boolean array to select the items we want from m_out. Because you want the element of the second column to come first, we have to use the last list comprehension.

Note that it requires to create at least 2 N boolean arrays, which might be even more wasteful than the first solution... Both solutions can easily be applied to more columns than 2, though.

1 Comment

Thanks for the concise list comp solution. That is what i was originally attempting to do.

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.