如何基于已知目标索引将整数数组独热编码为包含缺失索引的NumPy矩阵?
给定NumPy数组 [5, 2, 4, 6, 3],期望得到如下独热编码矩阵:
[[0, 0, 0, 0, 0, 1, 0], [0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 1, 0, 0, 0]]
使用Pandas的pd.get_dummies(original_array).values方法看似简单,但存在一个缺陷:最终矩阵不会包含缺失索引对应的列(如本例中的0、1)。若预先已知目标列的完整索引范围(此处为0到6的所有整数),请问从初始数组出发,生成上述矩阵的最高效方法是什么?
高效解决方案
嘿,这个问题我之前处理过好几次,其实有几个靠谱的方案,尤其是当你已经明确知道目标索引范围的时候,纯NumPy的方法是效率最高的,当然也可以结合Pandas来实现,下面给你详细说说:
方法一:NumPy原生索引构造(最优选择)
这种方法完全基于NumPy的底层数组操作,没有额外的冗余步骤,时间复杂度是O(n),几乎是理论最优的:
import numpy as np original_array = np.array([5, 2, 4, 6, 3]) target_classes = 7 # 因为索引范围是0到6,一共7个类别 # 初始化一个全0的矩阵,形状为(数组长度, 类别数) one_hot_matrix = np.zeros((len(original_array), target_classes), dtype=int) # 利用高级索引,在对应的位置填充1 one_hot_matrix[np.arange(len(original_array)), original_array] = 1 print(one_hot_matrix)
运行这段代码就能直接得到你想要的矩阵,原理很简单:我们先创建一个符合要求的全0矩阵,然后用数组的索引位置(每行对应原数组的一个元素)和元素本身的值(对应列的位置)来定位,把这些位置设为1即可。
方法二:Pandas补全缺失列(适合Pandas场景)
如果你正在处理Pandas数据,不想切换到纯NumPy的话,可以先用get_dummies生成初始编码,再用reindex补全缺失的列:
import pandas as pd import numpy as np original_array = np.array([5, 2, 4, 6, 3]) # 把数组转成Series,生成初始独热编码 dummies_df = pd.get_dummies(pd.Series(original_array)) # 重新索引,指定0到6的所有列,缺失的列填充0 dummies_df = dummies_df.reindex(columns=np.arange(7), fill_value=0) # 转成NumPy数组 one_hot_matrix = dummies_df.values print(one_hot_matrix)
不过这种方法因为涉及到DataFrame的操作,效率会比纯NumPy方法低一些,适合已经在Pandas工作流里的情况。
为什么直接用get_dummies不行?
正如你注意到的,pd.get_dummies只会根据原数组中实际出现的类别生成列,所以像0、1这种没在原数组里出现的类别就会被漏掉。而reindex的作用就是强制把这些缺失的列补回来,并用0填充,这样就能得到完整的独热编码矩阵了。
内容的提问来源于stack exchange,提问作者Jivan

