You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Numpy邻域单元格计算环绕平均与基础运算

问题描述

我有一个10×10的Numpy数组,需要对每个单元格完成两个计算:

  • 基于其上下左右邻域单元格计算指标(公式为|邻域值-当前值|/(邻域值+当前值))
  • 基于单元格的i、j索引做加权移动平均:8个紧邻单元格权重占比70%,16个非紧邻单元格权重占比30%
    同时不确定如何处理边缘(边界及角落)单元格的窗口核不完整问题,寻求Pythonic的实现方式。
用户代码尝试
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

noisy_data = [[0.0467251, 0.0529133, 0.0775945, 0.0640082, 0.0439774, 0.0915829,
        0.0547699, 0.0826791, 0.0883616, 0.0977739],
       [0.0875183, 0.0790368, 0.101146 , 0.0777582, 0.104289 , 0.0775479,
        0.156569 , 0.0999909, 0.0905242, 0.161871 ],
       [0.1427   , 0.1211   , 0.15661  , 0.113337 , 0.135986 , 0.1384   ,
        0.181515 , 0.159102 , 0.200004 , 0.187535 ],
       [0.163381 , 0.186425 , 0.174798 , 0.14191  , 0.1514   , 0.166044 ,
        0.199063 , 0.146319 , 0.173303 , 0.144067 ],
       [0.182485 , 0.16901  , 0.11     , 0.127162 , 0.0858656, 0.1564   ,
        0.161187 , 0.0588985, 0.110706 , 0.0560944],
       [0.103804 , 0.109948 , 0.0707144, 0.0493536, 0.0471329, 0.0708205,
        0.048201 , 0.0487304, 0.069967 , 0.0947939],
       [0.0382397, 0.0918   , 0.101197 , 0.102453 , 0.135943 , 0.0867575,
        0.123071 , 0.0970329, 0.099906 , 0.101536 ],
       [0.113361 , 0.167597 , 0.141526 , 0.0792396, 0.118    , 0.065764 ,
        0.0915817, 0.1183   , 0.149376 , 0.118608 ],
       [0.10647  , 0.1566   , 0.1303   , 0.139754 , 0.174465 , 0.148458 ,
        0.187625 , 0.132805 , 0.171687 , 0.158161 ],
       [0.15319  , 0.174204 , 0.161628 , 0.127377 , 0.173368 , 0.145292 ,
        0.208068 , 0.168076 , 0.14961  , 0.124334 ]]

noisy_data = np.array(noisy_data).reshape(10, 10)

plt.imshow(noisy_data, cmap="jet")
plt.colorbar()

new_df = pd.DataFrame()
# 注:原代码存在语法错误(括号不匹配)和逻辑错误(循环变量遍历数组而非索引)
new_df['left_neighboring_index'] = [(np.abs(noisy_data[i-1] - noisy_data[i]))/(noisy_data[i-1] + noisy_data[i])  for i in noisy_data]
new_df['right_neighboring_index'] = [(np.abs(noisy_data[i+1] - noisy_data[i]))/(noisy_data[i+1] + noisy_data[i])  for i in noisy_data]
new_df['bottom_neighboring_index'] = [(np.abs(noisy_data[j-1] - noisy_data[j]))/(noisy_data[j-1] + noisy_data[j])  for i in noisy_data]
new_df['top_neighboring_index'] = [(np.abs(noisy_data[j+1] - noisy_data[j]))/(noisy_data[j+1] + noisy_data[j])  for i in noisy_data]

new_df['weighted_moving_average_size_20_(8+12)'] = ...?
解决方案

一、邻域指标计算

原代码核心问题是循环逻辑错误,需遍历数组的行、列索引而非数组元素。边缘单元格无对应邻域,可直接赋值NaN,或通过补边处理。

实现代码

import numpy as np
import pandas as pd

noisy_data = np.array(noisy_data).reshape(10, 10)
rows, cols = noisy_data.shape

# 初始化结果数组,默认填充NaN
left_idx = np.full((rows, cols), np.nan)
right_idx = np.full((rows, cols), np.nan)
top_idx = np.full((rows, cols), np.nan)
bottom_idx = np.full((rows, cols), np.nan)

# 计算内部单元格的邻域指标(排除边缘行/列)
for i in range(1, rows-1):
    for j in range(1, cols-1):
        current = noisy_data[i, j]
        # 左邻域
        left_val = noisy_data[i, j-1]
        left_idx[i, j] = np.abs(left_val - current) / (left_val + current)
        # 右邻域
        right_val = noisy_data[i, j+1]
        right_idx[i, j] = np.abs(right_val - current) / (right_val + current)
        # 上邻域
        top_val = noisy_data[i-1, j]
        top_idx[i, j] = np.abs(top_val - current) / (top_val + current)
        # 下邻域
        bottom_val = noisy_data[i+1, j]
        bottom_idx[i, j] = np.abs(bottom_val - current) / (bottom_val + current)

# 转为DataFrame
new_df = pd.DataFrame({
    'left_neighboring_index': left_idx.flatten(),
    'right_neighboring_index': right_idx.flatten(),
    'top_neighboring_index': top_idx.flatten(),
    'bottom_neighboring_index': bottom_idx.flatten()
})

二、加权移动平均计算

定义5×5窗口:中心为当前单元格,8个3×3范围内的紧邻单元格权重占70%(每个权重0.7/8),16个5×5外围单元格权重占30%(每个权重0.3/16)。用np.pad的edge模式补边,解决边缘窗口不完整问题。

基础循环实现

# 定义5×5权重核
kernel = np.zeros((5, 5))
# 3×3区域(除中心):8个紧邻单元格
kernel[1:4, 1:4] = 0.7 / 8
kernel[2, 2] = 0  # 中心单元格不参与计算
# 外围区域:16个单元格
kernel[0, :] = 0.3 / 16
kernel[4, :] = 0.3 / 16
kernel[:, 0] = 0.3 / 16
kernel[:, 4] = 0.3 / 16

# 补边处理边缘
padded_data = np.pad(noisy_data, pad_width=2, mode='edge')

# 初始化结果数组
weighted_avg = np.zeros_like(noisy_data)

# 遍历计算加权平均
for i in range(rows):
    for j in range(cols):
        window = padded_data[i:i+5, j:j+5]
        weighted_avg[i, j] = np.sum(window * kernel)

# 加入DataFrame
new_df['weighted_moving_average'] = weighted_avg.flatten()

高效向量化实现(推荐)

用scipy.ndimage.convolve替代循环,大幅提升效率:

from scipy.ndimage import convolve

# 复用之前定义的权重核
kernel = np.zeros((5, 5))
kernel[1:4, 1:4] = 0.7 / 8
kernel[2, 2] = 0
kernel[0, :] = 0.3 / 16
kernel[4, :] = 0.3 / 16
kernel[:, 0] = 0.3 / 16
kernel[:, 4] = 0.3 / 16

# mode='nearest'自动补边处理边缘
weighted_avg = convolve(noisy_data, kernel, mode='nearest')
new_df['weighted_moving_average_vectorized'] = weighted_avg.flatten()

内容的提问来源于stack exchange,提问作者2023_resolution

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 20:05:39