Python处理含NaN的坐标数组时索引报错且无法识别NaN问题
问题根源与解决方法
1. NaN判断错误的原因
- 不能用
is或者==判断NaN:NaN是IEEE浮点数规范定义的特殊值,核心特性是np.nan == np.nan返回False;而is判断的是对象的内存地址,numpy数组中存储的NaN是数值类型的元素,和全局的np.nan对象不是同一个内存地址,因此c131x[-1] is np.nan必然返回False。 np.vectorize用法错误:np.vectorize的作用是将普通函数转换为支持数组广播的函数,你直接将数组传入np.vectorize得到的是一个函数对象,不是原数组,自然无法检测到NaN。
2. 正确检测与截断NaN的方法
用numpy内置的np.isnan()函数专门检测NaN值,你提到仅填充位置存在NaN,也就是有效数据连续、仅尾部有NaN,可以写一个通用的尾部NaN截断函数:
import numpy as np import pandas as pd from scipy.spatial import distance_matrix def truncate_tail_nan(arr: np.ndarray) -> np.ndarray: """截断数组尾部连续的NaN,返回有效部分""" nan_positions = np.where(np.isnan(arr))[0] # 数组中没有NaN直接返回 if len(nan_positions) == 0: return arr # 取第一个出现NaN的位置作为截断点 first_nan_idx = nan_positions[0] return arr[:first_nan_idx]
3. 修复原有代码的步骤
第一步:处理坐标数组,去除NaN并对齐xy坐标
df = pd.read_csv('contours_20150210.csv') def process_contour(x_col: str, y_col: str) -> np.ndarray: """读取并处理单组轮廓坐标,返回无NaN的[N,2]坐标数组""" x = truncate_tail_nan(np.asarray(df[x_col])) y = truncate_tail_nan(np.asarray(df[y_col])) # 对齐x和y的长度,取较短的为准避免坐标错位 valid_len = min(len(x), len(y)) return np.column_stack((x[:valid_len], y[:valid_len])) # 处理所有轮廓 c131 = process_contour("contour_131_x", "contour_131_y") c193 = process_contour("contour_193_x", "contour_193_y") c211 = process_contour("contour_211_x", "contour_211_y")
第二步:计算最近邻
此时坐标数组已经没有任何NaN值,计算距离矩阵不会出现全NaN的行,原有报错会消失,还可以用numpy内置方法替代循环提高效率:
dist_193_211 = distance_matrix(c193, c211) # 直接沿axis=1取最小值和对应索引,无需循环 min_dist = dist_193_211.min(axis=1) min_idx = dist_193_211.argmin(axis=1) # 合并成你需要的[索引, 距离]格式 nn_193_211 = np.column_stack((min_idx, min_dist)).tolist()
内容的提问来源于stack exchange,提问作者weaselskinghenry
相关产品推荐
相关产品推荐

