在 Python 中应避免的五个常见数据清洗错误

在 Python 中应避免的五个常见数据清洗错误

(Five Common Data Cleaning Mistakes To Avoid In Python)

4 分钟 阅读 发现 Python 中最常见的五个数据清洗错误,并学习有效策略以避免它们,从而获得可靠且高质量的数据集。
(0 评论)
在 Python 中清理数据至关重要,但也充满可能削弱分析结果的陷阱。本文强调五个最常见的数据清洗错误,并提供可执行的技巧来避免它们,从而确保更准确、高效的数据工作流。
在 Python 中应避免的五个常见数据清洗错误

在 Python 中要避免的五个常见数据清洗错误

每一个成功的数据科学项目的基础都是干净、前后一致的数据。然而,在分析的快节奏过程中,即使是经验丰富的 Python 用户也有时会踩到可预防的数据预处理陷阱。无论你是在为机器学习模型准备数据,还是为可视化做准备,知道需要留意哪些错误可以为你省下数不清的挫折时间,并带来更稳健的结果。

让我们分解 Python 中最常见(而且往往致命)的五个数据清洗错误,附有实用技巧和示例,以帮助你让工作流保持坚如磐石且高效。

Blindly Dropping or Filling Missing Values

missing data, data cleaning, pandas, null values

一个现实世界数据集中最先遇到的问题之一就是缺失数据。在 Python 中,尤其是使用像 pandas 这样的工具时,替换或删除 NaN 非常简单:df.dropna()df.fillna(0) 一行就能完成。但简单并不等于正确。

Why This Is a Problem

自动删除包含缺失值的行会大幅缩小数据集,或者在缺失性与其他变量相关联的情况下引入偏差。用均值或零填充值会扭曲分布,尤其是在非数值列或存在离群值的情况下。

When This Happens

请看下面的代码片段:

# Too hasty with missing value treatment
import pandas as pd

df = pd.read_csv('survey.csv')
df = df.dropna()  # Danger: goodbye valuable data!

如果只有一个可选字段(例如年龄)缺失的行达到 30%,你将损失 30% 的数据。如果缺失的年龄主要集中在某个特定人群,那么结果将变成一个不再能准确代表总体的数据集。

Actionable Advice

  • 行动前先检查:使用 df.isnull().sum()df.info() 查看缺失模式。
  • 考虑情境:例如,在医疗数据中缺失的年龄可能需要一个特殊标记(“未知”)而不是删除或填充。
  • 利用诸如插补之类的技术:考虑使用 sklearn.impute.SimpleImputer 进行有据可依的填充,或使用领域特定的逻辑。
  • 记录每一步数据清洗过程:添加注释,解释 为什么 删除或填充值,确保未来用户的透明度。

Failing to Fix Inconsistent Data Formats and Encodings

data formats, encoding errors, pandas dtype, string cleaning

来自多个来源的数据很少能整齐地符合单一格式。日期、类别和字符串编码特别容易出现微妙、难以追踪的错误。

示例陷阱

  • 日期列格式混用 'YYYY/MM/DD', 'MM-DD-YY', 与 'dd.mm.yyyy'。
  • 将 'abc'、'Abc'、'aBc' 视为不同条目。
  • 作为字符串导入的整数列 (dtype: object),使数值运算不可用。
  • 具有隐藏字符编码问题的文本文件,导致数据不可读或出现隐藏的 NaN。

经典 Python 问题:

# Date times imported as strings, causing issues
import pandas as pd

df = pd.read_csv('sales.csv')
df['created_at'].min()  # Only finds the minimum string, not chronological min

最佳实践

  • 始终检查数据类型df.dtypes 能快速暴露本应为数值型但实际不是的列。
  • 主动转换数据:在导入数据后尽早使用 pd.to_datetime()pd.to_numeric() 和类别转换。
  • 标准化文本:对于类别列使用 .str.lower().str.strip();用一致的值替换同义词或拼写错误。
  • 编码很重要:在读取数据时,尤其来自未知或非 UTF-8 的来源,指定 encoding 参数(encoding='utf-8'encoding='cp1252')。

示例:在 pandas 中强制保持一致的日期时间

df['created_at'] = pd.to_datetime(df['created_at'], errors='coerce')
df = df.dropna(subset=['created_at'])  # Remove rows where dates couldn't parse

一点小心就能防止日后花费数小时调试奇怪的分析结果。

Ignoring Outliers Without Contextual Investigation

outliers, box plot, anomaly detection, data validation

离群值是数据清洗中的变数—有时它们表示数据录入错误;另一些时候,它们恰恰是值得研究的事件!

常见错误

在不考虑上下文的情况下,自动脚本删除超出某个范围的数值,可能既删除错误数据,也剥夺了重要信号。

示例

# Don't just drop anything >200 without context
bp_outliers = df[df['blood_pressure'] > 200]
print(bp_outliers)  # Investigate: are these errors or medically relevant cases?

推荐的方法

  • 先做概况分析:使用 df.describe() 以及箱线图、直方图等可视化来揭示分布细节并发现离群值。
  • 调查极端值:将它们与有效的领域边界进行比较,查阅文档或咨询领域专家。
  • 标记,而不是立即删除:为了下游的鲁棒性,将异常值标记以便进一步审核,而不是立即丢弃。
  • 记录业务逻辑:如果你确实在删除或调整,请解释原因(例如,“BMI 低于 10 被视为输入错误”)。

当离群值被证明是有效的时,它们可以重新塑造基于数据的商业洞察。

Mishandling Duplicate Entries

duplicates, pandas drop_duplicates, data integrity, repeated records

重复数据无处不在——数据输入错误、网页抓取或系统故障都会引入它们。虽然 Python 能瞬间使用 df.drop_duplicates(),但真正的危险在于误解重复项来自何处,或如何最好地解决它们。

何处会出错

一个零售数据库可能因为重复的系统提交而让同一客户订单有多行记录。只有在每一列都匹配时,删除除其中一行之外的所有重复项才有效;否则,信息可能会丢失。

示例:

# Problematic: Dropping all duplicates based only on 'order_id'
df = df.drop_duplicates(subset=['order_id'])  # Could lose different addresses or notes attached to split-row orders

如果像 'delivery_notes' 之类的列在行之间不同,盲目删除重复项要么丢失数据,要么无法调和冲突信息。

洞察与可执行步骤

  • 按所有关键列审计重复项:使用 df.duplicated(subset=key_cols, keep=False) 来标记真正的重复。
  • 去重前聚合:例如,合并字符串数据(注释)或对相同订单号的每日销售数量求和。
  • 保留你的‘金本’:有时,保留原数据并将其标记为 is_duplicate 以用于下游分析,比直接删除更可取。
  • 合并后再检查:许多重复项在通过连接或追加合并数据集后悄然出现。

下面是去重前聚合可能有用字段的示例:

def collapse_order_notes(notes):
    return '; '.join(sorted(set(x for x in notes if pd.notnull(x))))

rollup = df.groupby('order_id').agg({
    'customer_id': 'first',
    'total_amount': 'sum',
    'delivery_notes': collapse_order_notes
}).reset_index()

这能保护重要的辅助数据。

Overlooking Categorical Data Encoding

categorical data, label encoding, one-hot, sklearn

许多强大的算法需要数值输入,而不是直接的字符串标签或类别。对分类列进行编码是一个关键步骤,但匆忙选择或选择错误的方法会降低模型性能并引入错误。

常见错误

  • 朴素标签编码:用任意数值代码替换类别——例如 A=0、B=1、C=2——没有隐含的序数意义,即使对于基于树的模型也是如此。
  • One-hot 编码爆炸:为高基数类别创建如此多的列,以致模型变得不可用。
  • 生产环境中的静默不匹配:在一种编码顺序下训练模型,但在另一组未见的类别上进行评分,导致结果错配。

示例:

from sklearn.preprocessing import LabelEncoder, OneHotEncoder

# Label encoding ignores category meaning
le = LabelEncoder()
df['city_code'] = le.fit_transform(df['city'])  # Problem: Model interprets numbers mathematically

专家处理方法

  • 有序 vs 名义型:仅在标签具有自然顺序时才使用数值编码(如尺寸:S < M < L)。否则,选择 one-hot 或其他编码。
  • 控制 one-hot 粒度:使用 pd.get_dummies(df, drop_first=True, dummy_na=False),或对于大基数特征,考虑哈希或目标编码。
  • 保持编码的一致性:序列化并重复使用编码器(例如,使用 sklearn 的 fit/transform),以便模型部署获得相同的映射——这是在现实世界输入出现新的、未见过的类别时的一个经典陷阱。

示例:带可控内存的一键热编码

city_counts = df['city'].value_counts()
# Only encode cities appearing at least 10 times
common_cities = city_counts[city_counts > 10].index
df['city'] = df['city'].apply(lambda x: x if x in common_cities else 'Other')
df = pd.get_dummies(df, columns=['city'], drop_first=True)

这使特征规模保持在可控范围,并使模型更稳健。

避免这些错误将使你脱颖而出

数据清洗在 Python 中需要对细微的细节与速度同样讲究。通过避免机械化或上下文无关的清洗,你的数据科学与分析工作将远高于平均水平。带着目的性地检查缺失值、统一格式、把离群值视为信号而不仅仅是噪声、仔细审视重复项,并在分类编码方面进行策略性思考。

掌握了这些经验并具备对数据的批判性眼光,你将减少回溯的时间、在生产环境中降低出错概率,并建立起分析师信任的数据管道工程声誉。在日益增长的数据科学领域,成为那个让数据真正具备洞察力的人,确实是一种超能力。

评分文章

添加评论和评价

用户评论

基于 0 条评论
5 颗星
0
4 颗星
0
3 颗星
0
2 颗星
0
1 颗星
0
添加评论和评价
我们绝不会与任何人分享您的电子邮件。