在数据科学领域,数据清洗是一个不可或缺的步骤。本文是“使用Python和Pandas进行数据清洗”系列文章的一部分,旨在帮助开发者快速掌握数据科学工具和技术。如果想查看本系列的其他文章,可以在这里找到它们:第一部分 - 介绍Jupyter和Pandas;第二部分 - 将CSV和SQL数据加载到Pandas中;第三部分 - 在Pandas中修正缺失数据;第四部分 - 在Pandas中合并多个数据集;第五部分 - 在Pandas DataFrame中清洗数据;第六部分 - 在Pandas DataFrame中重塑数据;第七部分 - 使用Seaborn和Pandas进行数据可视化。
现在,已经将客户、产品和购买数据合并到一个DataFrame中,将在重塑之前对数据集进行最后一次清理。请注意,为这个系列的模块创建了一个完整的Jupyter Notebook,其中包含源数据文件,可以下载并本地安装。
当前的数据集不包含任何缺失值,但可能仍然包含一些不合理的值或不正确的数据类型。让看看如何找到并清理这类数据。
由于DataFrame是从三组数据合并而来的,因此在数据集本身周围存在一些不一致性。为了纠正这一点,让删除一些重复的键并重命名其他一些键。首先,让开始一个新的代码块,并使用以下方法删除重复的标识符:
combinedData.drop(columns=['customer_num'], inplace=True)
combinedData.drop(columns=['product_num'], inplace=True)
这将删除'customer_num'和'product_num'列。Pandas还可以重命名列,让将三个"id"列重命名为更具代表性的名称:
combinedData = combinedData.rename(columns={
'id_x': 'purchase_id',
'id_y': 'customer_id',
'id': 'product_id'
})
这将重命名列ID为其对应的来源,并清理表格相当多。
数据不匹配的另一个大原因是找到字段中与键的意图不一致的数据。例如,可能在数字中混入了字符串值。让检查数据集,看看是否有任何相关问题。
print(combinedData.dtypes)
print(combinedData.head(2))
正如从结果中看到的,大部分数据被泛化为对象,只有少数键被归类为数字(int64)。让尝试将'purch_date'键转换为datetime,并看看是否会出现任何问题。
print(pd.to_datetime(combinedData['purch_date'], errors='coerce').isnull().value_counts())
这个代码块现在尝试将'purch_date'列中的所有值转换,并计算出现错误(True)或成功(False)的次数。幸运的是,这次没有错误(第一个和第二个数字匹配)。
让扩展这个代码块,检查数字和货币键:
print(pd.to_numeric(combinedData['amount'], errors='coerce').isnull().value_counts())
print(pd.to_numeric(combinedData['paid'], errors='coerce').isnull().value_counts())
print(pd.to_numeric(combinedData['cost'], errors='coerce').isnull().value_counts())
如果现在查看数字,'paid'和'cost'错误,'amount'值也有两个错误。'cost'和'paid'列应该很容易修复,因为Pandas不处理带有美元符号($)的货币值。将通过以下方法在检查之前从'amount'键中删除所有美元符号:
combinedData['paid'] = combinedData['paid'].str.replace('$', '')
combinedData['cost'] = combinedData['cost'].str.replace('$', '')
当运行这个清理并检查时,'cost'错误已经被修复,但'paid'键仍然有很多错误。让找出哪些值导致错误,通过以下方法引发错误:
print(pd.to_numeric(combinedData['paid'], errors='raise'))
看起来值在千位处也包含逗号分隔符,所以也将去掉这些:
combinedData['paid'] = combinedData['paid'].str.replace(',', '')
combinedData['cost'] = combinedData['cost'].str.replace(',', '')
现在,当运行这个清理阶段时,只剩下两个错误了。让改变'amount'以引发错误,看看问题是什么。看起来字符串已经滑入了两行。由于这是一个如此小的数字,将把所有的键转换为正确的类型,并删除任何具有空值的行,这应该只有两行。
combinedData['paid'] = combinedData['paid'].str.replace('$', '')
combinedData['cost'] = combinedData['cost'].str.replace('$', '')
combinedData['paid'] = combinedData['paid'].str.replace(',', '')
combinedData['cost'] = combinedData['cost'].str.replace(',', '')
combinedData['purch_date'] = pd.to_datetime(combinedData['purch_date'], errors='coerce')
combinedData['amount'] = pd.to_numeric(combinedData['amount'], errors='coerce')
combinedData['paid'] = pd.to_numeric(combinedData['paid'], errors='coerce')
combinedData['cost'] = pd.to_numeric(combinedData['cost'], errors='coerce')
combinedData.dropna(subset=['amount'], inplace=True)
print(combinedData.isnull().sum())
print(combinedData.shape)
print(combinedData.dtypes)