Replace data of an array by 2 values of a second array

前端 未结 2 1679
小鲜肉
小鲜肉 2021-01-15 18:20

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

相关标签:
2条回答
  • 2021-01-15 18:34

    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.

    0 讨论(0)
  • 2021-01-15 18:53

    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.]])
    
    0 讨论(0)
提交回复
热议问题