如何从列表中提取高频值前半部分并解决numpy排序异常问题
问题根源
np.column_stack拼接数组时会将所有列强制转换为统一的兼容数据类型。如果原始mat_sup中存储的是字符串类值,拼接后第二列的计数字段会从整数被转为字符串格式,后续排序会按照字符串字典序执行(例如字符串规则下'10'会排在'2'前面),最终排序结果和数值排序的预期不符。
可直接复用的解决方案
核心思路是拆分接收np.unique的返回值,避免提前拼接导致计数列类型被转换,以下两种方案都可以实现需求:
方案1:直接基于计数数组排序(写法最简洁)
不需要创建结构化数组,显式转换计数类型后直接排序,代码如下:
# 分开接收唯一值、对应计数,避免类型被自动转换 vals, counts = np.unique(mat_sup, return_counts=True) # 将计数显式转为整数类型,按计数降序生成排序索引 sorted_index = (-counts.astype(int)).argsort() # 按索引重组值和计数 sorted_result = np.column_stack((vals[sorted_index], counts[sorted_index])) # 提取出现频率最高的前半部分值 top_half_values = sorted_result[:len(sorted_result)//2, 0]
方案2:保留结构化数组排序的写法
如果习惯用结构化数组的排序逻辑,创建结构化数组前先显式转换计数的类型即可:
vals, counts = np.unique(mat_sup, return_counts=True) # 提前把计数转为整数类型,避免后续字符串排序问题 counts_int = counts.astype(int) # 创建结构化数组、生成排序索引 sorted_index = np.core.records.fromarrays([counts_int], names='a').argsort() # argsort默认是升序排序,翻转后得到计数从高到低的结果 sorted_result = np.column_stack((vals[sorted_index][::-1], counts_int[sorted_index][::-1])) # 提取出现频率最高的前半部分值 top_half_values = sorted_result[:len(sorted_result)//2, 0]
注意:
argsort()默认返回从小到大的升序索引,如果需要按计数从高到低取Top值,要么给计数值加负号做升序模拟降序效果,要么排序完成后翻转数组顺序。
内容的提问来源于stack exchange,提问作者tibibou
相关产品推荐
相关产品推荐

