如何迭代或递归地确定二维数组中的邻居?

4

我尝试使用Python 3.7确定二维数组中的相邻元素。

该数组如下所示:

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

首先需要确定最大值位置为(2,4), 然后想要获取其邻居的非nan值。以下是代码:
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)
   

结果是:
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]])

好的,没问题。实际上,我想使用新的“1”值来确定它们的邻居,也就是确定(1,3),(3,3)和(3,4)位置的邻居。重复此过程直到从(2,4)位置开始的所有具有值的位置被确定。结果将是这样的:

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

接下来,我想确定其余未标识值的最大值,以重复此过程,直到此二维数组中所有邻居位置的值都被确定。最终结果应如下所示:

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

我的母语不是英语,如果有任何关于描述的问题,请告诉我,我会尽力说明。如果有人能帮助我,我将非常感激。


1
我不完全清楚你需要什么。有点相关的是,numpy 有一个滑动窗口函数(https://numpy.org/devdocs/reference/generated/numpy.lib.stride_tricks.sliding_window_view.html),可以在类似这样的情况下很有用。 - logicOnAbstractions
非常感谢。但是我不理解你所提到的方法如何使用。 - Searuru
1
@Searuru,这与将数组中的非NaN值切换为1有什么不同?我不明白你的问题。你对中间结果感兴趣吗? - qouify
@qouify 实际上,我已经按照上述要求完成了第二个结果。我已经在下面附上了它。但是我无法递归确定它。 - Searuru
1
@Searuru 你应该阅读文档并试着使用这个方法。但基本上,不是你必须以某种方式迭代你的数据......滑动窗口将为你返回一个更大的数组。有点像你做的所有迭代的连接。但好处是每个元素只是你需要进行单个迭代所需的数据。 - logicOnAbstractions
@logicOnAbstractions 我已经通过递归过程完成了这个程序。非常感谢你。请查看下面的代码。 - Searuru
2个回答

1
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

逐步完成,第二个结果已经完成。

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)

然而,这只是一个例子。我的数据集有超过一万行和列。因此,我想递归地完成这个目标。我尝试以下代码:
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)

没问题。我懂了!


我完成了!就在刚才。 - Searuru

0

我完成了。代码如下:

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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接