本文为 Python 60 Days Challenge 课程学习整理,原作者与原 Notebook 链接见「课程资料」。代码按章节顺序运行;语法示意和故意报错的反例已单独标注。
数据准备: 将课程仓库中的 data.csv/data.xlsx 放在 Notebook 的当前工作目录,路径已移除原作者电脑的盘符。读取 Excel 需要 openpyxl。各节额外依赖按文中安装说明准备。
本次校订: 标称类别(例如房屋所有权)没有天然大小关系。编码只是表示方式;缺失类别可显式表示,OneHotEncoder 应只在训练集拟合并处理未知类别。
打卡任务
- 阅读本节讲义或 Notebook
- 跑通示例代码
- 整理 3 个关键点
- 完成当日打卡输出
课程资料
- 训练营讲义:https://docs.qq.com/doc/DTFhndExSRGNHS3B6?nlc=1
- GitHub 仓库:https://github.com/cheer932041235/Python60DaysChallenge
- 本日 Notebook:Day5 离散特征的处理(独热编码).ipynb
学习内容
今天的任务分成以下几步
- 读取数据
- 找到所有离散特征
- 选择一个离散特征进行独热编码
- 采取循环对所有离散特征进行独热编码
- 加上昨天的内容 并且处理所有缺失值
# 读取数据
import pandas as pd
data = pd.read_csv('data.csv') # 此时data是一个DataFrame对象
data.columns
# 打印所有的离散变量名
# 在python中对于变量名常常用英文含义和下划线来命名,而不借助拼音,这是便于他人阅读和理解代码的一种习惯。
# 连续的英文是continuous,离散的英文是discrete
for discrete_features in data.columns:
if data[discrete_features].dtype == 'object':
print(discrete_features)
# 以Home Ownership为例,打印观察下
data['Home Ownership']
# 需要进行编码,打印这个变量的值
# vakue_counts()方法用于统计每个类别的个数,并返回一个Series对象。这个方法可以帮助我们快速了解数据集中每个类别的分布情况。
data['Home Ownership'].value_counts()
- Home Ownership:房屋所有权
- Rent:租房
- Own Home:拥有自有住房
- Have Mortgage:有抵押贷款
可以发现并不具备顺序关系,因此可以采用one-hot编码
# 对Home Ownership列进行独热编码
data = pd.get_dummies(data, columns=['Home Ownership'])
data.columns
可以看到之前的Home Ownership已经被替换成了'Home Ownership_Have Mortgage','Home Ownership_Home Mortgage', 'Home Ownership_Own Home','Home Ownership_Rent'
data.head()
# 可以看到上面独热编码后的数据是bool类型,试着转换为int类型,因为后续可能有的函数计算不支持bool值
# 学习类型转换的方法
data['Home Ownership_Have Mortgage'] =data ['Home Ownership_Have Mortgage'].astype(int)
data['Home Ownership_Have Mortgage']
到此为止,已经掌握了对离散变量做独热编码的所有方法
- 找到离散变量
- 独热编码映射
- 转换独热编码到int类型
- 填补每一列的缺失值
# 现在尝试结合之前的代码一次性对所有离散特征独热编码
# 重新读取数据
data = pd.read_csv('data.csv')
# 找到离散变量
discrete_lists = [] # 新建一个空列表,用于存放离散变量名
for discrete_features in data.columns:
if data[discrete_features].dtype == 'object':
discrete_lists.append(discrete_features)
# 离散变量独热编码
data = pd.get_dummies(data, columns=discrete_lists, drop_first=True)
data.columns
此时还有个困难,如何找到所有独热编码后的新特征名呢?
# 对比独热编码前后的列名 即可
data2 = pd.read_csv('data.csv')
list_final = [] # 新建一个空列表,用于存放独热编码后新增的特征名
for i in data.columns:
if i not in data2.columns:
list_final.append(i) # 这里打印出来的就是独热编码后的特征名
list_final
# 其实还可以通过data.columns.difference()方法来实现,请自行学习
# 可以看到 想要实现一个结果有很多不同方法
# 接着之前的,对bool特征进行类型转换
for i in list_final:
data[i] = data[i].astype(int) # 这里的i就是独热编码后的特征名
data.head()
# 填补每一列的缺失值
data.dtypes
data.isnull().sum() # 统计每一列的缺失值个数
# 用均值填补
# 循环遍历这个列表中的每一列
for i in data.columns:
if data[i].isnull().sum() > 0: # 找到存在缺失值的列
#计算该列的均值
mean_value = data[i].mean()
#用均值填充缺失值
data[i] = data[i].fillna(mean_value) # 显式赋值,兼容 pandas Copy-on-Write
data.isnull().sum()
刚才这段代码中出现了一个警告,我们昨天说到了这个警告没什么用,但是会影响你的观感。
import warnings
# 保留警告,便于发现弃用接口和数值问题。 # 忽略警告信息
现在在py文件中 一次性处理data数据中所有的连续变量和离散变量
- 读取data数据
- 对离散变量进行one-hot编码
- 对独热编码后的变量转化为int类型
- 对所有缺失值进行填充
那么这样有没有问题呢?实际上是存在逻辑问题的
原则上应该先填补缺失值再独热编码,如果顺序颠倒的话,用众数补全,比如北京上海深圳001,有可能三个数的众数都是0,就会变成000。
那么对于object对象如何填补缺失值呢?大家尝试自己借助AI来实现
这里作为课后作业
此外,大家其实非常喜欢问我,预处理、描述性统计、特征筛选等等流程谁先谁后,实际上没有严格的顺序,你自己要能把握住主线,ai经常在这里犯错。
当你指出ai的错误的时候,他会告诉你你说的对。----希望大家也很快出现这一时刻.
来点人生哲理小课堂
一定要实践,不要丧失自己的主体性,任何丧失主体性的行为最后一定是南辕北辙。
Day5 离散特征的处理(独热编码)
本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
评论交流
欢迎留下你的想法