使用Python进行数据清洗:从原始数据到可用数据集
在数据分析和机器学习的流程中,数据清洗(Data Cleaning)是一个至关重要的步骤。无论你的模型多么先进、算法多么高效,如果输入的数据质量不高,最终结果很可能也会是“垃圾”。本文将介绍如何使用 Python 进行常见的数据清洗操作,并提供可运行的代码示例。
我们将围绕一个模拟的销售数据集来演示数据清洗过程,包括处理缺失值、重复值、异常值以及格式标准化等常见问题。
准备工作
首先,我们需要安装必要的库:
pip install pandas numpy matplotlib seaborn
然后导入所需的 Python 模块:
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltimport seaborn as sns
加载数据
我们使用 pandas
加载一个 CSV 格式的销售数据文件:
# 假设你有一个名为 'sales_data.csv' 的文件df = pd.read_csv('sales_data.csv')# 显示前5行数据print(df.head())
输出可能如下所示(根据你的数据不同而变化):
OrderID Product Quantity Price Date0 1001 Laptop 2 999.99 2023-01-011 1002 Mouse 5 19.99 2023-01-012 1003 Keyboard 3 49.99 2023-01-023 1004 Monitor 1 299.99 2023-01-024 1005 Speaker 4 79.99 2023-01-03
检查数据基本信息
# 查看数据的基本信息print(df.info())# 查看是否有缺失值print(df.isnull().sum())# 查看是否有重复行print(df.duplicated().sum())
假设输出如下:
<class 'pandas.core.frame.DataFrame'>RangeIndex: 1000 entries, 0 to 999Data columns (total 5 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 OrderID 1000 non-null int64 1 Product 998 non-null object 2 Quantity 995 non-null float64 3 Price 997 non-null float64 4 Date 999 non-null object dtypes: float64(2), int64(1), object(2)memory usage: 39.1+ KBNoneOrderID 0Product 2Quantity 5Price 3Date 1dtype: int640
我们可以看到存在一些缺失值,但没有重复行。
处理缺失值
方法一:删除含有缺失值的行
# 删除缺失值较多的行df_cleaned = df.dropna()# 查看是否还存在缺失值print(df_cleaned.isnull().sum())
方法二:填充缺失值
对于数值型字段(如 Quantity
, Price
),可以使用均值或中位数填充:
df['Quantity'] = df['Quantity'].fillna(df['Quantity'].median())df['Price'] = df['Price'].fillna(df['Price'].mean())
对于字符串型字段(如 Product
, Date
),可以用众数或指定字符串填充:
df['Product'] = df['Product'].fillna(df['Product'].mode()[0])df['Date'] = df['Date'].fillna('Unknown')
处理异常值
假设我们想查看 Quantity
和 Price
是否有明显异常值。
# 绘制箱线图查看异常值plt.figure(figsize=(12, 5))plt.subplot(1, 2, 1)sns.boxplot(x=df['Quantity'])plt.title('Boxplot of Quantity')plt.subplot(1, 2, 2)sns.boxplot(x=df['Price'])plt.title('Boxplot of Price')plt.show()
我们可以看到某些订单的数量或价格可能异常高或低。一种常见的做法是使用 IQR 法则 来识别并剔除异常值:
# 计算 IQRQ1 = df['Price'].quantile(0.25)Q3 = df['Price'].quantile(0.75)IQR = Q3 - Q1# 筛选出非异常值df = df[~((df['Price'] < (Q1 - 1.5 * IQR)) | (df['Price'] > (Q3 + 1.5 * IQR)))]print("After removing outliers:", len(df))
统一数据格式
日期格式统一
有时候日期格式不一致,比如有的写成 2023/01/01
,有的写成 01-Jan-2023
,我们可以用 pd.to_datetime()
统一格式:
df['Date'] = pd.to_datetime(df['Date'], errors='coerce')
数值单位统一
假设 Price
单位有时为美元,有时为人民币,需要统一货币单位。这里以转换人民币为例:
exchange_rate = 7.2 # USD to CNYdf['Price_CNY'] = df['Price'] * exchange_rate
类型转换与特征工程
类型转换
确保字段类型正确:
df['Quantity'] = df['Quantity'].astype(int)df['Price'] = df['Price'].astype(float)
特征工程:添加销售额字段
df['Sales'] = df['Quantity'] * df['Price']print(df[['Quantity', 'Price', 'Sales']].head())
输出:
Quantity Price Sales0 2 999.99 1999.981 5 19.99 99.952 3 49.99 149.973 1 299.99 299.994 4 79.99 319.96
保存清洗后的数据
最后,将清洗后的数据保存为新的 CSV 文件:
df.to_csv('cleaned_sales_data.csv', index=False)
总结
通过以上步骤,我们完成了对销售数据集的完整清洗流程,包括:
缺失值处理(删除或填充)异常值检测与剔除数据格式标准化(日期、单位等)数据类型转换与特征工程这些步骤不仅适用于销售数据,也适用于大多数结构化数据集的预处理工作。掌握这些技能可以帮助你在后续的数据分析、可视化或建模过程中获得更准确的结果。
十、附录:完整代码汇总
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltimport seaborn as sns# 加载数据df = pd.read_csv('sales_data.csv')# 查看数据基本信息print(df.info())print(df.isnull().sum())print(df.duplicated().sum())# 处理缺失值df['Quantity'] = df['Quantity'].fillna(df['Quantity'].median())df['Price'] = df['Price'].fillna(df['Price'].mean())df['Product'] = df['Product'].fillna(df['Product'].mode()[0])df['Date'] = df['Date'].fillna('Unknown')# 删除重复行df = df.drop_duplicates()# 转换日期格式df['Date'] = pd.to_datetime(df['Date'], errors='coerce')# 异常值处理Q1 = df['Price'].quantile(0.25)Q3 = df['Price'].quantile(0.75)IQR = Q3 - Q1df = df[~((df['Price'] < (Q1 - 1.5 * IQR)) | (df['Price'] > (Q3 + 1.5 * IQR)))]# 类型转换df['Quantity'] = df['Quantity'].astype(int)df['Price'] = df['Price'].astype(float)# 添加销售额字段df['Sales'] = df['Quantity'] * df['Price']# 可视化异常值plt.figure(figsize=(12, 5))plt.subplot(1, 2, 1)sns.boxplot(x=df['Quantity'])plt.title('Boxplot of Quantity')plt.subplot(1, 2, 2)sns.boxplot(x=df['Price'])plt.title('Boxplot of Price')plt.show()# 保存数据df.to_csv('cleaned_sales_data.csv', index=False)
如果你正在构建自己的数据科学项目,建议将数据清洗部分封装为函数或类,以便于复用和维护。希望这篇文章能帮助你更好地理解和应用数据清洗技术!
如有任何问题,欢迎留言交流!