如何高效将sklearn加载的Iris数据集数值型species转为分类值
更优的数值-分类值转换方案
你目前用的「自定义if-else判断 + apply逐行应用」的实现可以跑通,但代码冗余、运行效率低,还容易出现手写类名的拼写错误,以下几种方案从简洁度、运行效率上都更适合这个场景:
1. 直接复用sklearn数据集自带的类别映射,零手写成本
sklearn加载的Iris数据集本身就内置了数值到类名的对应关系(存储在target_names属性中),完全不需要自己手写判断逻辑,从根源上避免手动拼错类名的问题:
# 构建数值与类名的映射字典,直接从数据集属性读取 species_map = dict(zip(range(len(iris.target_names)), iris.target_names)) # 用pandas向量化map完成转换,替代逐行apply iris['species'] = iris['species'].map(species_map)
这种方式的优势:
map是pandas底层C实现的向量化操作,运行速度远高于逐行Python循环的apply方法——尤其当数据量增大时,两者的效率差会被放大数十倍- 不需要手动输入类名字符串,完全复用数据集的标准定义,不会出现拼写错误
2. 一步生成带正确分类值的DataFrame,省掉中间转换步骤
其实你前面拆分特征、拼接表、修改列名、做数值转换的整个流程,完全可以压缩为更短的代码,还能自动生成分类类型的字段,降低后续分析的内存占用:
# 直接基于原始数据集生成特征列的DataFrame iris_df = pd.DataFrame( data=iris.data, columns=['sepal_length','sepal_width','petal_length','petal_width'] ) # 直接把数值目标转为pandas分类类型,不需要额外apply转换 iris_df['species'] = pd.Categorical.from_codes(iris.target, categories=iris.target_names)
这种方式生成的species字段是pandas内置的分类(Categorical)类型,存储相同内容时的内存占用仅为普通字符串列的1/3~1/10,后续做分组、绘图操作的效率也更高。
3. 通用场景下的字典映射,替代多分支if-else
如果遇到没有内置映射关系的数值字段,也推荐用字典构造映射规则后配合map完成转换,完全不需要写多分支判断函数:
# 构造数值与类名的对应字典 species_map = {0: 'setosa', 1: 'versicolor', 2: 'virginica'} iris['species'] = iris['species'].map(species_map)
和自定义函数+apply的方式相比,这种写法代码更短、运行效率更高,后续如果新增类别值,只需要在字典里加一行映射规则即可,不需要修改判断逻辑。
不推荐的写法:逐行
loc筛选赋值(比如iris.loc[iris['species']==0, 'species'] = 'setosa'),虽然比apply速度快,但需要重复写多次布尔筛选代码,简洁度远不如map方案。
内容的提问来源于stack exchange,提问作者rajtilakjee
相关产品推荐
相关产品推荐

