I have two numpy arrays \"Elements\" and \"nodes\". My aim is to gather some data of these arrays. I need to remplace \"Elements\" data of the two last columns by the two co
Here's a version that does not use a loop:
The inputs:
In [115]: Elements = np.array([[1.,11.,14.],[2.,12.,13.]])
In [116]: nodes = np.array([[11.,0.,0.],[12.,1.,1.],[13.,2.,2.],[14.,3.,3.]])
The ids from Elements
as a vector; make it int
for easy comparison:
In [117]: e = Elements[:,1:].ravel().astype(int)
In [118]: e
Out[118]: array([11, 14, 12, 13])
Similar ids from nodes
:
In [119]: n=nodes[:,0].astype(int)
In [120]: n
Out[120]: array([11, 12, 13, 14])
Compare e
with n
using broadcasting - that makes a 4x4 array of True/False. Use where
to find their coordinates:
In [121]: I, J = np.where(e==n[:,None])
In [122]: I
Out[122]: array([0, 1, 2, 3], dtype=int32)
In [123]: J
Out[123]: array([0, 2, 3, 1], dtype=int32)
In [124]: e[J]
Out[124]: array([11, 12, 13, 14])
In [125]: n[I]
Out[125]: array([11, 12, 13, 14])
And magically we can now match up node ids with elements ids. Print some intermediate arrays if this action is unclear.
Make a results
array, one row per element of e
, and copy the corresponding nodes
values over.
In [131]: results = np.zeros((e.shape[0],2),nodes.dtype)
In [132]: results[J] = nodes[I,1:]
In [133]: results
Out[133]:
array([[ 0., 0.],
[ 3., 3.],
[ 1., 1.],
[ 2., 2.]])
Join results
with the initial column of Elements:
In [134]: np.concatenate((Elements[:,[0]],results.reshape(2,4)),axis=1)
Out[134]:
array([[ 1., 0., 0., 3., 3.],
[ 2., 1., 1., 2., 2.]])
where
does the basic matching. Most of rest is just reshaping and type conversion to handle the fact that the 'slots' we need to fill are 2 columns of the 3 column Elements array.
Just out of curiousity, I figured how to use the Elements ids without raveling:
In [149]: e2 = Elements[:,1:].astype(int)
In [150]: I,J,K = np.where(e2==n[:,None,None])
In [151]: results2 = np.zeros((e2.shape[0],e2.shape[1],2),nodes.dtype)
In [152]: results2[J,K] = nodes[I,1:]
In [153]: results2.reshape(2,4) # still requires a reshape
Out[153]:
array([[ 0., 0., 3., 3.],
[ 1., 1., 2., 2.]])