Home > Blockchain >  How to iteratively or recursively determine neighbors in a two-dimensional array?
How to iteratively or recursively determine neighbors in a two-dimensional array?

Time:10-25

I try to determine neighbors in a two-dimensional array using Python 3.7.

The array is like this:

array([[ 1.,  2., nan, nan,  5.],
       [nan,  2., nan,  5., nan],
       [nan,  2.,  4., nan,  6.],
       [nan, nan, nan,  5.,  5.],
       [nan, nan, nan, nan, nan],
       [ 1.,  2.,  4., nan, nan],
       [ 1.,  2., nan, nan,  4.],
       [nan,  4., nan, nan,  5.]])

Firstly, the maximum value needs to be determined and the position is (2,4), then I want to get its neighbors with not nan values. The code is as follows:

test_arr = np.array([[1,2,np.nan,np.nan,5], 
                     [np.nan,2,np.nan,5,np.nan],
                     [np.nan,2,4,np.nan,6],
                     [np.nan,np.nan,np.nan,5,5],
                     [np.nan,np.nan,np.nan,np.nan,np.nan], 
                     [1,2,4,np.nan,np.nan],
                     [1,2,np.nan,np.nan,5],
                     [np.nan,4,np.nan,np.nan,6]])
row = test_arr.shape[0] 
col = test_arr.shape[1] 
temp_amatrix = np.matrix(test_arr)
p = np.argwhere(test_arr == np.nanmax(temp_amatrix)).flatten()[0]
q = np.argwhere(test_arr == np.nanmax(temp_amatrix)).flatten()[1]
def neighbours(test_arr_in,countnotnan_in):
    for r in range(len(np.where(countnotnan_in==1)[0])):
        x = np.where(countnotnan_in == 1)[0][r]
        y = np.where(countnotnan_in == 1)[1][r]
        indexlist = [[x-1,y-1],[x-1,y],[x-1,y 1],[x,y-1],[x,y 1],[x 1,y-1],[x 1,y],[x 1,y 1]]
        for c in indexlist:
            if 0 <= c[0] < row and 0 <= c[1] < col:
                if np.isnan(test_arr_in[c[0],c[1]]) == False:
                    countnotnan_in[c[0],c[1]] = 1
    return countnotnan_in
countnotnan = np.zeros_like(test_arr)
countnotnan[p][q] = 1 
notnan_arr = neighbours(test_arr,countnotnan)
   

The result is:

notnan_arr = array([[ 0, 0, 0, 0, 0],
                    [ 0, 0, 0, 1, 0],
                    [ 0, 0, 0, 0, 1],
                    [ 0, 0, 0, 1, 1],
                    [ 0, 0, 0, 0, 0],
                    [ 0, 0, 0, 0, 0],
                    [ 0, 0, 0, 0, 0],
                    [ 0, 0, 0, 0, 0]])

Yes, it is OK. Actually, I want to use the new '1' values to determine thier neighbors, i.e. determining the neighbors of (1,3), (3,3) and (3,4) positions. Repeat this process until all positions with values starting from the position of (2,4) are identified. The result will be this:

notnan_arr = array([[ 1, 1, 0, 0, 1],
                    [ 0, 1, 0, 1, 0],
                    [ 0, 1, 1, 0, 1],
                    [ 0, 0, 0, 1, 1],
                    [ 0, 0, 0, 0, 0],
                    [ 0, 0, 0, 0, 0],
                    [ 0, 0, 0, 0, 0],
                    [ 0, 0, 0, 0, 0]])

Next, I want to determine the maximum value of the rest unidentified value to repeat the process until all neighbors' position with values of this two-dimensional array are identified. And the final result should be like this:

notnan_arr = array([[ 1, 1, 0, 0, 1],
                    [ 0, 1, 0, 1, 0],
                    [ 0, 1, 1, 0, 1],
                    [ 0, 0, 0, 1, 1],
                    [ 0, 0, 0, 0, 0],
                    [ 1, 1, 1, 0, 0],
                    [ 1, 1, 0, 0, 1],
                    [ 0, 1, 0, 0, 1]])

My mother tongue is not English, if anyone has any question about the description. Please tell me, I will try my best to state it. And if anyone can help me, I would be very grateful.

CodePudding user response:

def neighbours(test_arr_in,fstnotnan_in,count_in,countused_in):
    for r in range(len(np.where(fstnotnan_in==1)[0])):
        x = np.where(count_in == 1)[0][r]
        y = np.where(count_in == 1)[1][r]
        if  np.isnan(countused_in[x][y]) == True:
            continue
        else:
            countused_in[x,y] = np.nan
            indexlist = [[x-1,y-1],[x-1,y],[x-1,y 1],[x,y-1],[x,y 1],[x 1,y-1],[x 1,y],[x 1,y 1]]
            for c in indexlist:
                if 0 <= c[0] < row and 0 <= c[1] < col:
                    if np.isnan(test_arr_in[c[0],c[1]]) == False:
                        fstnotnan_in[c[0],c[1]] = 1
    count_in = np.where(fstnotnan_in == 1,1.,0)
    return fstnotnan_in,count_in,countused_in

test_arr = np.array([[1,2,np.nan,np.nan,5],
                     [np.nan,2,np.nan,5,np.nan],
                     [np.nan,2,4,np.nan,6], 
                     [np.nan,np.nan,np.nan,5,5],
                     [np.nan,np.nan,np.nan,np.nan,np.nan],
                     [1,2,4,np.nan,np.nan],
                     [1,2,np.nan,np.nan,5],
                     [np.nan,4,np.nan,np.nan,6]])
row = test_arr.shape[0] 
col = test_arr.shape[1]
temp_amatrix = np.matrix(test_arr)
p = np.argwhere(test_arr == np.nanmax(temp_amatrix)).flatten()[0]
q = np.argwhere(test_arr == np.nanmax(temp_amatrix)).flatten()[1]
countused = np.zeros_like(test_arr)
fstnotnan = np.zeros_like(test_arr)
count = np.full((row,col),np.nan)
fstnotnan[p,q] = 1
count[p,q] = 1

Step by step, the second result was completed.

fstnotnan_out,count_out,countused_out = neighbours(test_arr,fstnotnan,count,countused)
fstnotnan_out1,count_out1,countused_out1 = neighbours(test_arr,fstnotnan_out,count_out,countused_out)
fstnotnan_out2,count_out2,countused_out2 = neighbours(test_arr,fstnotnan_out1,count_out1,countused_out1)
fstnotnan_out3,count_out3,countused_out3 = neighbours(test_arr,fstnotnan_out2,count_out2,countused_out2)
fstnotnan_out4,count_out4,countused_out4 = neighbours(test_arr,fstnotnan_out3,count_out3,countused_out3)

However, this is just an example. My dataset has more than ten thousand rows and cols. So I want to recursively accomplish the goal. And I try the code as below:

def neighbours(test_arr_in,fstnotnan_in,count_in,countused_in):
    if (np.where(fstnotnan_in== 1)[0].shape[0] == np.where(np.isnan(countused_in))[0].shape[0]) == True:
        return fstnotnan_in,count_in,countused_in
    else:
        for r in range(len(np.where(fstnotnan_in==1)[0])):
            x = np.where(count_in == 1)[0][r]
            y = np.where(count_in == 1)[1][r]
            if  np.isnan(countused_in[x][y]) == True:
                continue
            else:
                countused_in[x,y] = np.nan
                indexlist = [[x-1,y-1],[x-1,y],[x-1,y 1],[x,y-1],[x,y 1],[x 1,y-1],[x 1,y],[x 1,y 1]]
                for c in indexlist:
                    if 0 <= c[0] < row and 0 <= c[1] < col:
                        if np.isnan(test_arr_in[c[0],c[1]]) == False:
                            fstnotnan_in[c[0],c[1]] = 1
        count_in = np.where(fstnotnan_in == 1,1.,0)
        return neighbours(test_arr_in,fstnotnan_in,count_in,countused_in)

It's OK. I got it!

CodePudding user response:

I finished it. The code is as follows:

def sechmax(arr_in):
    temp_amatrix = np.matrix(arr_in)
    r_max = np.argwhere(arr_in == np.nanmax(temp_amatrix)).flatten()[0]
    c_max = np.argwhere(arr_in == np.nanmax(temp_amatrix)).flatten()[1]
    return r_max,c_max 

def neighbours(arr_in,fstnotnan_in,countused_in):
    if (np.where(fstnotnan_in == 1)[0].shape[0] == np.where(np.isnan(countused_in))[0].shape[0]):
        n_arr_in = np.where(countused_in == 0,arr_in,np.nan)
        if np.isnan(n_arr_in).all():
            return fstnotnan_in,countused_in
        else:
            r_max,c_max = sechmax(n_arr_in)
            fstnotnan_in[r_max,c_max] = 1
            return neighbours(n_arr_in,fstnotnan_in,countused_in)
    else:
        count = fstnotnan_in.copy()
        for r in range(len(np.where(fstnotnan_in==1)[0])):
            x = np.where(count == 1)[0][r]
            y = np.where(count == 1)[1][r]
            if  np.isnan(countused_in[x][y]):
                continue
            else:
                countused_in[x,y] = np.nan
                indexlist = [[x-1,y-1],[x-1,y],[x-1,y 1],[x,y-1],[x,y 1],[x 1,y-1],[x 1,y],[x 1,y 1]]
                for c in indexlist:
                    if 0 <= c[0] < row and 0 <= c[1] < col:
                        if np.isnan(arr_in[c[0],c[1]]) == False:
                            fstnotnan_in[c[0],c[1]] = 1
        return neighbours(arr_in,fstnotnan_in,countused_in)

test_arr = np.array([[1,2,np.nan,np.nan,5],
                    [np.nan,2,np.nan,5,np.nan],
                    [np.nan,2,4,np.nan,6],
                    [np.nan,np.nan,np.nan,5,5],
                    [np.nan,np.nan,np.nan,np.nan,np.nan],
                    [1,2,4,np.nan,np.nan],
                    [1,2,np.nan,np.nan,5],
                    [np.nan,4,np.nan,np.nan,6]])
row = test_arr.shape[0] 
col = test_arr.shape[1]
r_max,c_max = sechmax(test_arr)
countused = np.zeros_like(test_arr)
fstnotnan = np.zeros_like(test_arr)
fstnotnan[r_max,c_max] = 1
fstnotnan_out,countused_out = neighbours(test_arr,fstnotnan,countused)
  • Related