Python 使用相邻值平均值更新2darray中给定值的所有元素

Python 使用相邻值平均值更新2darray中给定值的所有元素,python,pandas,numpy,Python,Pandas,Numpy,考虑一个2darray数字数组,其中一个特定值(即0)表示“无数据”。在某些情况下,可能需要用相邻单元的值更新这些无数据值。例如,我有两个网格相互重叠-一个有地块ID,另一个有到主要城市的交通时间。有些ID只会重叠,没有数据传输时间单元。在这里,仅仅使用相邻网格单元的平均值实际上是一个不错的猜测。然而,更多地关注抽象问题,考虑下面的设置 v_shp_ids = np.array([[1, 1, 1, 1], [1, 1, 1, 1],

考虑一个2darray数字数组,其中一个特定值(即0)表示“无数据”。在某些情况下,可能需要用相邻单元的值更新这些无数据值。例如,我有两个网格相互重叠-一个有地块ID,另一个有到主要城市的交通时间。有些ID只会重叠,没有数据传输时间单元。在这里,仅仅使用相邻网格单元的平均值实际上是一个不错的猜测。然而,更多地关注抽象问题,考虑下面的设置

v_shp_ids = np.array([[1, 1, 1, 1],
                      [1, 1, 1, 1],
                      [1, 1, 1, 1],
                      [1, 1, 1, 1]])

v_shp_ids = v_shp_ids.ravel()

raster = np.array([[0, 0, 0, 0],
                   [0, 0, 0, 0],
                   [0, 0, 1, 0],
                   [0, 0, 0, 0]])

raster_r = raster.ravel()

zs = pd.concat([pd.Series(v_shp_ids), pd.Series(raster_r)], axis=1)
这里,v_shp_ID表示地块ID 1由所有单元格表示。raster表示只有一个单元格具有值。我想用1填充光栅。(从一个简单的案例开始)

这是我的解决方案

 # Dictionary to store no data updates
na_update = {}

# Num rows in raster 2darray
i_end = len(raster)
# Num cols in raster 2darray
j_end = len(raster[0])
# Hard coding nodata = 0 for the example arrays I input above
nodata = 0

# Number of raster cells with no data
fill_length = len(zs.loc[zs[1] == nodata])
# Copy the dataframe for no data raster cells only
zs_na = zs.loc[zs[1] == nodata].copy()

# While the updated data dictionary is not full, loop
while len(na_update) != fill_length:
    # For each 1darray index in the df
    for ind, row in zs_na.iterrows():
        # get the corresponding raster grid cell
        i = ind // j_end
        j = ind % j_end
        # get the slice of neighboring pixel cells and flatten
        neighb = raster[max(i-1,0):min(i+2,i_end),
                        max(j-1,0):min(j+2,j_end)].flatten()
        # get the average of these neighboring, excluding na values
        neighb_avg = np.ma.masked_values(neighb, nodata).mean()
        # store average in dictionary if we can and update the pixels
        if neighb_avg is not np.ma.masked:
            na_update[ind] = neighb_avg.astype(raster_r.dtype)
            raster[i, j] = na_update[ind]
    # update the df to the remaining pixels with na remaining
    zs_na = zs_na[~zs_na.index.isin(na_update.keys())]

我知道卷积可能是一种方法,但我的一些担心是 a) 我不想计算每个单元格的最近邻平均值,因为在许多情况下,我不处理无数据单元格 b) 我无法事先确定使用什么样的邻域大小来确保所有无数据单元都获得值,并且为了确保它们都获得值,邻域可能太大,无法继续成为合理的近似值(当然,您可能会认为整个方法不是合理的近似值)

我有两个主要问题

  • 有没有一种方法可以使用数据帧(甚至光栅网格)上的索引来做同样的事情?我曾经尝试过zs.loc[zs[1]==nodata,1]=#的各种变体,试图获取光栅栅格中相邻元素的平均值

  • 我是否完全错过了填充无数据单元格的合理方法


  • 我发现这是一个很有趣的问题,我非常期待大家的想法/讨论。

    这里有一个非常有用的rasterio函数:

    该函数是来自rasterio.fill模块的fillnodata。根据描述:

    通过插值填充光栅数据中的孔

    此算法将为所有指定节点数据插值 像素(在遮罩中用零标记)。每个像素有四个方向 二次曲线搜索用于查找要从中插值的值(使用逆 距离加权)。插值所有值后,零或更多 平滑迭代(插值像素上的3x3平均滤波器)为 应用于平滑瑕疵

    函数调用是

    rasterio.fill.fillnodata(image, mask=None, max_search_distance=100.0, smoothing_iterations=0)
    
    我就进去了

    rasterio.fill.fillnodata(image = np.ma.masked_array(raster, nodata))
    

    下面是一个非常有用的光栅功能:

    该函数是来自rasterio.fill模块的fillnodata。根据描述:

    通过插值填充光栅数据中的孔

    此算法将为所有指定节点数据插值 像素(在遮罩中用零标记)。每个像素有四个方向 二次曲线搜索用于查找要从中插值的值(使用逆 距离加权)。插值所有值后,零或更多 平滑迭代(插值像素上的3x3平均滤波器)为 应用于平滑瑕疵

    函数调用是

    rasterio.fill.fillnodata(image, mask=None, max_search_distance=100.0, smoothing_iterations=0)
    
    我就进去了

    rasterio.fill.fillnodata(image = np.ma.masked_array(raster, nodata))
    

    我想补充一点,我认为光栅[I,j]=na_update[ind]应该移到for循环之外,而是将while循环的每次迭代中更新的单元索引存储在一个字典中,然后循环并更新光栅。这避免了给恰好是第一个(虽然我认为更快)捕获到另一个错误的单元格赋予优先级的问题。我用了一个方阵作为例子,所以忽略了这一点。必须切换num row和num col分配我想补充的是,我认为光栅[I,j]=na_update[ind]应该移到for循环之外,而是将while循环的每次迭代中更新的单元索引存储在一个字典中,然后循环并更新光栅。这避免了给恰好是第一个(虽然我认为更快)捕获到另一个错误的单元格赋予优先级的问题。我用了一个方阵作为例子,所以忽略了这一点。必须切换num row和num col赋值您应该在答案中总结您的解决方案,而不是在问题中。您当前的答案与其说是真实答案,不如说是评论。虽然此链接可以回答问题,但最好在此处包含答案的基本部分,并提供链接供参考。如果链接页面发生更改,仅链接的答案可能无效。-对不起,这是我的第一个问题/答案。我希望编辑足够了。如果是这样,我会接受这个答案,但会推迟到进一步审查。你应该在答案中总结你的解决方案,而不是在问题中。您当前的答案与其说是真实答案,不如说是评论。虽然此链接可以回答问题,但最好在此处包含答案的基本部分,并提供链接供参考。如果链接页面发生更改,仅链接的答案可能无效。-对不起,这是我的第一个问题/答案。我希望编辑足够了。如果是的话,我会接受这个答案,但会推迟到进一步的审查