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

前端 未结 2 1680
小鲜肉
小鲜肉 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条回答
  •  -上瘾入骨i
    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.]])
    

提交回复
热议问题