Skip to content Skip to sidebar Skip to footer

Replace Data Of An Array By 2 Values Of A Second Array

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 coordinates con

Solution 1:

Instead of appending the results to some array or list, you may consider creating the resulting array before you go through the loop.

Here is my solution for you problem using a fop loop and np.where.

import numpy as np
# I used numpy 1.10.1 here

Elements = np.array([[1.,11.,14.],[2.,12.,13.]])
nodes = np.array([[11.,0.,0.],[12.,1.,1.],[13.,2.,2.],[14.,3.,3.]])

# Create an array with enough rows and five columns
res = np.zeros((np.shape(Elements)[0],5))

for i in range(np.shape(Elements)[0]):
    res[i,0] = Elements[i,0] # The first column stays the same# Find the Value of the 2nd column of Elements in the first column of nodes.
    nodesindex = np.where(nodes[:,0]==Elements[i,1])
    # Replace second and third row of the results with the ventries from nodes.
    res[i,1:3]=nodes[nodesindex,1:3]

    #Do the same for the 3rd column of Elements
    nodesindex = np.where(nodes[:,0]==Elements[i,2])
    res[i,3:5]=nodes[nodesindex,1:3]

print(res)

which gives as output

[[ 1.  0.  0.  3.  3.]
[ 2.  1.  1.  2.  2.]]

There may be pure numpy solutions (without the for-loop). That then might be much faster than this.

Solution 2:

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.]])

Post a Comment for "Replace Data Of An Array By 2 Values Of A Second Array"