基于Numpy实现决策树学习器时的索引链式调用问题
你遇到的核心问题是全局排序索引i是针对整个x数组的,不能直接用子集n去索引i来得到子集的排序结果。要复用全局排序的结果,得从全局排序索引里筛选出属于n的行号,并且保留它们的排序顺序。
给你两种实用的实现方式:
方法一:按列逐个处理(直观易懂)
对每个特征列,从全局排序索引里挑出属于n的行号,再用这些行号提取对应列的排序后数据:
import numpy as np x = np.array([[1,8,7,4,3,9,0,2,5,6], [7,5,3,8,9,4,6,10,2,1]]).T i = np.argsort(x, 0) n = np.nonzero(x[:, 0] < 6)[0] # 初始化结果数组,匹配子集n的形状 sorted_x_n = np.empty((len(n), x.shape[1]), dtype=x.dtype) for col in range(x.shape[1]): # 从当前列的全局排序索引中,筛选出属于n的行号(保留排序顺序) valid_global_indices = i[:, col][np.isin(i[:, col], n)] # 提取对应列的排序后数据 sorted_x_n[:, col] = x[valid_global_indices, col] print(sorted_x_n)
输出结果和np.sort(x[n], axis=0)完全一致,但复用了之前的全局排序索引,避免了重复排序。
方法二:向量化实现(高效适配多特征列)
如果特征列数量较多,用向量化操作代替循环能提升效率:
import numpy as np x = np.array([[1,8,7,4,3,9,0,2,5,6], [7,5,3,8,9,4,6,10,2,1]]).T i = np.argsort(x, 0) n = np.nonzero(x[:, 0] < 6)[0] # 生成布尔矩阵,标记全局排序索引中哪些行属于子集n mask = np.isin(i, n) # 按列提取有效索引并生成排序后的子集数据 sorted_x_n = np.array([x[i[mask[:, col], col], col] for col in range(x.shape[1])]).T
原理和方法一一致,只是用矩阵操作简化了显式循环。
原代码错误原因
x[i[n], np.arange(2)]的问题在于:i[n]取的是全局排序索引的前len(n)行,这些行对应的是整个x的排序位置,和子集n没有对应关系。比如第二列的全局排序索引是针对整个x第二列的,直接取i[n,1]得到的行号大概率不在n里,自然无法得到x[n]的排序结果。
内容的提问来源于stack exchange,提问作者NotProbable
相关产品推荐
相关产品推荐

