代码之家  ›  专栏  ›  技术社区  ›  Nihilum

在Python上合并数组而不求其重叠单元格的和

  •  0
  • Nihilum  · 技术社区  · 2 年前

    我有不同数量的数组,它们的大小和数据类型都相同。他们的细胞(称为 pixels 在我的代码中)要么有一个浮点数,要么有一个NaN。 我想合并这些数组,但有3个特定的标准。如果是一个像素(称为重叠像素):

    • 至少有2个数组有一个值(非NaN):将1个输入数组的值仅指定给合并数组中的重叠像素。
    • 只有一个输入数组有一个值,将该输入数组的像素值指定给合并数组中的重叠像素。
    • 如果没有一个输入数组具有特定像素的值,我们将写入 np.nan 在重叠像素中。

    为了做到这一点,我有一个循环通过每个像素,并评估有多少个输入数组有一个值。为了满足第一个条件,我编写了一组if/elif/else条件。为了满足第二个标准 else 我的一部分情况只是 np.nansum (因为除1个阵列外,所有阵列在该特定像素处都有NAN)。

    我写了一个完全没有效率的函数,而且非常有限。如何改进代码,以便处理要合并的可变数组数量?(超过3个阵列)。

    我的代码:

    import numpy as np
    
    def merger(*args):
    
        # This function evaluates pixel per pixel the values of 2 to 3 arrays the same size. 
        # Each pixel either has a value or a NaN. We want to merge the arrays without summing their values at overlapping pixels.
        # If at least two arrays have a value for an intersecting pixel, we pick one of the array's value to attribute to the merging pixel in the new array.
    
    
        # If we have 2 arrays to merge
        if len(args) == 2:
          
          C = np.empty([args[0].shape[0], args[0].shape[1], args[0].shape[2]],dtype=float)
          
          for b in range(args[0].shape[0]):
            for i in range(args[0].shape[1]):
              for j in range(args[0].shape[2]):
    
                # If the two similar pixels have a value, take the value of the first array
                if np.isnan(args[0][b,i,j]) == False and np.isnan(args[1][b,i,j]) == False:
    
                  C[b,i,j] = args[0][b,i,j]
    
                # If all of the pixels are NaN, we input a NaN
                elif np.isnan(args[0][b,i,j]) == True and np.isnan(args[1][b,i,j]) == True:
    
                  C[b,i,j] = np.nan
                
                # Else, take the nansum of the two pixels (because one is a NaN, the other will be the real value)
                else:
                  C[b,i,j] = np.nansum([args[0][b,i,j],args[1][b,i,j]])
    
          
        # If we have 3 arrays to merge (A1, A2 and A3) 
        if len(args) == 3:
          
          C = np.empty([args[0].shape[0], args[0].shape[1], args[0].shape[2]],dtype=float)
          
          for b in range(args[0].shape[0]):
            for i in range(args[0].shape[1]):
              for j in range(args[0].shape[2]):
    
                # If A1 and A2 have a value but not A3, pick the value of A1. If A1 and A3 have a value but not A2, pick the value of A1
                if np.isnan(args[0][b,i,j]) == False and np.isnan(args[1][b,i,j]) == False and np.isnan(args[2][b,i,j]) == True or np.isnan(args[0][b,i,j]) == False and np.isnan(args[2][b,i,j]) == False and np.isnan(args[1][b,i,j]) == True:
    
                  C[b,i,j] = args[0][b,i,j]
    
                # If A2 and A3 have a value but not A1, pick the value of A2
                elif np.isnan(args[1][b,i,j]) == False and np.isnan(args[2][b,i,j]) == False and np.isnan(args[0][b,i,j]) == True:
    
                  C[b,i,j] = args[1][b,i,j]
    
                # If all the arrays have a value, pick the value of A3
                elif np.isnan(args[1][b,i,j]) == False and np.isnan(args[2][b,i,j]) == False and np.isnan(args[2][b,i,j]) == False:
    
                  C[b,i,j] = args[2][b,i,j]
    
                # If all of the pixels are NaN, we input a NaN
                elif np.isnan(args[1][b,i,j]) == True and np.isnan(args[2][b,i,j]) == True and np.isnan(args[2][b,i,j]) == True:
    
                  C[b,i,j] = np.nan
    
                # If only one array has a value, nansum will attribute this value to the pixel
                else:
                  C[b,i,j] = np.nansum([args[0][b,i,j],args[1][b,i,j], args[2][b,i,j]])
    
    
    
    
          return C
    
    
    
    # Example
    A1 = np.array([[[1, 1, 1],[np.nan, np.nan, np.nan], [1, np.nan, 1]],[[1, 1, 1],[np.nan, np.nan, np.nan], [1, np.nan, 1]]])
    A2 = np.array([[[1, np.nan, 1],[1, np.nan, np.nan], [1, np.nan, 1]],[[1, 1, 1],[np.nan, np.nan, 1], [np.nan, 1, 1]]])
    A3 = np.array([[[1, 1, 1],[np.nan, np.nan, 1], [np.nan, 1, 1]],[[1, np.nan, 1],[1, np.nan, np.nan], [1, np.nan, 1]]])
    
    
    merger(A1, A2, A3)
    
    array([[[ 1.,  1.,  1.],
            [ 1., nan,  1.],
            [ 1.,  1.,  1.]],
    
           [[ 1.,  1.,  1.],
            [ 1., nan,  1.],
            [ 1.,  1.,  1.]]])
    
    1 回复  |  直到 2 年前
        1
  •  1
  •   Chris    2 年前

    除非我遗漏了什么,否则这和用A2然后A3迭代替换A1 nan值有什么不同?因为你没有求和,你可以从其他数组中任意选取一个非空值。

    A1 = np.array([[[1, 1, 1],[np.nan, np.nan, np.nan], [1, np.nan, 1]],[[1, 1, 1],[np.nan, np.nan, np.nan], [1, np.nan, 1]]])
    A2 = np.array([[[1, np.nan, 1],[1, np.nan, np.nan], [1, np.nan, 1]],[[1, 1, 1],[np.nan, np.nan, 1], [np.nan, 1, 1]]])
    A3 = np.array([[[1, 1, 1],[np.nan, np.nan, 1], [np.nan, 1, 1]],[[1, np.nan, 1],[1, np.nan, np.nan], [1, np.nan, 1]]])
    
    
    A1[np.isnan(A1)] = A2[np.isnan(A1)]
    A1[np.isnan(A1)] = A3[np.isnan(A1)]
    print(A1)
    

    输出

    [[[ 1.  1.  1.]
      [ 1. nan  1.]
      [ 1.  1.  1.]]
    
     [[ 1.  1.  1.]
      [ 1. nan  1.]
      [ 1.  1.  1.]]]