缺失值处理:识别缺失值常用df.isnull().sum()或df.isna().any(),填充可用固定值、均值、中位数、前后向填充等方法,若缺失比例小或无保留价值可直接删除;2. 重复值处理:使用df.duplicated()识别重复行,df.drop_duplicates()删除重复记录,默认保留首次出现;3. 数据类型转换:用astype()进行类型转换,pd.to_datetime()和pd.to_numeric()分别用于日期和数值型字符串转换;4. 字符串/文本数据清洗:通过str.lower()、str.strip()、str.replace()等方法统一大小写、去除空格、替换字符;5. 异常值处理:识别可用z-score或iqr法,结合箱线图等可视化工具,处理方式包括删除、替换、转换或不处理,具体取决于业务背景和模型需求。

Python进行数据清洗,核心利器无疑是pandas库。它提供了一整套高效的数据结构和功能,帮助我们处理数据中常见的缺失、重复、格式不一、异常等问题,说白了,就是把那些“脏兮兮”的数据变得干净、规整,能真正为后续分析所用。

要说Python里怎么搞定数据清洗,pandas绝对是绕不开的话题。它提供了DataFrame这种表格型数据结构,操作起来跟Excel或者数据库表的感觉有点像,但效率和灵活性高得多。我通常会从以下几个方面入手:

1. 缺失值处理: 这是最常见的痛点。数据总会有“空洞”。
df.isnull().sum()能很快告诉你每列有多少缺失值,或者df.isna().any()看看有没有缺失。df['column'].fillna(0, inplace=True)
df['column'].fillna(df['column'].mean(), inplace=True)。这种方法挺常用,但得看数据分布,偏态分布时中位数可能更好。df['column'].fillna(method='ffill', inplace=True) 或 method='bfill'。这个在时间序列数据里特别好用,能保持数据的连续性。df.dropna(inplace=True)
df.dropna(axis=1, how='all', inplace=True)
import pandas as pd
import numpy as np
# 示例数据
data = {'A': [1, 2, np.nan, 4, 5],
'B': [np.nan, 2, 3, 4, np.nan],
'C': ['apple', 'banana', 'orange', np.nan, 'grape']}
df = pd.DataFrame(data)
print("原始数据:\n", df)
# 检查缺失值
print("\n缺失值统计:\n", df.isnull().sum())
# 填充缺失值 (以列'A'为例,用中位数填充)
df['A'].fillna(df['A'].median(), inplace=True)
# 填充缺失值 (以列'B'为例,前向填充)
df['B'].fillna(method='ffill', inplace=True)
# 删除列'C'中的缺失值行
df.dropna(subset=['C'], inplace=True)
print("\n处理缺失值后的数据:\n", df)2. 重复值处理: 数据录入或合并时,很容易出现重复记录。

df.duplicated()会返回一个布尔序列,指示哪些行是重复的。df.drop_duplicates(inplace=True)可以删除所有重复行,默认保留第一次出现的。如果想保留最后一次出现的,可以设置keep='last'。data_dup = {'ID': [1, 2, 2, 3, 4, 4],
'Value': ['A', 'B', 'B', 'C', 'D', 'D']}
df_dup = pd.DataFrame(data_dup)
print("\n原始重复数据:\n", df_dup)
print("\n重复行识别:\n", df_dup.duplicated())
df_dup.drop_duplicates(inplace=True)
print("\n删除重复行后的数据:\n", df_dup)3. 数据类型转换: 数据导入后,有时列的数据类型不是我们想要的,比如数字被识别成了字符串。
df['column'].astype(int) 或 df['column'].astype(float)
pd.to_datetime(df['date_column'])
pd.to_numeric(df['num_column'], errors='coerce')。errors='coerce'很重要,它可以把无法转换的值变成NaN,避免程序崩溃。df_type = pd.DataFrame({'num_str': ['10', '20', '30a', '40'],
'date_str': ['2023-01-01', '2023-01-02', '2023-01-03', '2023-01-04']})
print("\n原始数据类型:\n", df_type.dtypes)
df_type['num_str'] = pd.to_numeric(df_type['num_str'], errors='coerce')
df_type['date_str'] = pd.to_datetime(df_type['date_str'])
print("\n转换数据类型后的数据:\n", df_type.dtypes)
print("转换后的数据:\n", df_type)4. 字符串/文本数据清洗: 文本数据往往最“脏”,大小写不一、多余空格、特殊字符等等。
df['text_column'].str.lower() / .upper() 统一大小写df['text_column'].str.strip() 去除首尾空格df['text_column'].str.replace('old', 'new') 替换特定字符串df['text_column'].str.contains('keyword') 检查是否包含某个关键词df['text_column'].str.extract(r'(\d+)')
df_text = pd.DataFrame({'product': [' Apple ', 'banana_ ', 'Orange!', 'Grape']})
print("\n原始文本数据:\n", df_text)
df_text['product'] = df_text['product'].str.strip().str.lower().str.replace('!', '')
print("\n清洗后的文本数据:\n", df_text)5. 异常值处理: 这块比较复杂,异常值不一定都是“错”的,有时它们本身就很有意义。
df.boxplot())能直观显示异常点,散点图也能帮助发现。# IQR 方法识别异常值
Q1 = df['A'].quantile(0.25)
Q3 = df['A'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
# 假设我们在'A'列引入一个异常值
df.loc[0, 'A'] = 100 # 故意制造一个异常值
print("\n含异常值的数据:\n", df)
outliers = df[(df['A'] < lower_bound) | (df['A'] > upper_bound)]
print("\n识别到的异常值:\n", outliers)
# 处理异常值 (这里简单地用中位数替换)
# df.loc[(df['A'] < lower_bound) | (df['A'] > upper_bound), 'A'] = df['A'].median()
# print("\n处理异常值后的数据:\n", df)说实话,很多人在拿到数据的时候,第一反应可能就是赶紧跑模型、出结果。但往往忽略了最基础也是最重要的一步——数据清洗。在我看来,数据清洗不仅仅是一个技术操作,它更像是一场侦探游戏,你得仔细审视每一个数据点,理解它的来龙去脉。
立即学习“Python免费学习笔记(深入)”;
如果数据是脏的,比如有大量的缺失值、错误的数据类型、重复的记录,甚至是明显的异常值,那么你后续做的任何分析、构建的任何模型,都可能像建立在沙滩上的城堡,经不起推敲。用一句老话讲就是“Garbage In, Garbage Out”(垃圾进,垃圾出)。你喂给模型垃圾数据,它自然也只能吐出垃圾结果。
数据清洗能确保我们分析的可靠性。想象一下,你用包含了重复用户的数据去计算用户活跃度,结果肯定会虚高;或者用包含了错误编码的商品数据去分析销售趋势,那得到的结论多半是误导性的。清洗过程本身也是一个深入理解数据的过程,你会发现数据中隐藏的问题,甚至能从中发现一些有趣的模式或潜在的业务漏洞。所以,它不是可有可无的“体力活”,而是提升数据价值的基石。
这是一个经典问题,没有一劳永逸的答案,更多的是一种权衡和取舍。我个人在做决策时,通常会考虑几个关键点:
删除缺失值:
填充缺失值(Imputation):
最终的选择,往往是根据缺失值在数据集中的分布、缺失的模式(是随机缺失、条件缺失还是非随机缺失)、数据的业务含义以及后续分析或模型的具体需求来决定的。有时候,甚至可以尝试多种方法,然后通过交叉验证或模型表现来评估哪种处理方式更优。没有银弹,只有最适合当前场景的方案。
识别和处理异常值,这事儿比缺失值和重复值更让人头疼,因为“异常”这个词本身就带着主观色彩。一个值是异常,可能是数据录入错误,也可能是真实世界里一个非常罕见的事件。所以,在动手之前,我总会先问自己:这个“异常”到底意味着什么?
识别异常值的方法:
统计方法:
from scipy.stats import zscore df['zscore_A'] = np.abs(zscore(df['A'].dropna())) # 对非缺失值计算 # 找出 Z-score 超过阈值的行 # outliers_z = df[df['zscore_A'] > 3]
Q1 - 1.5 * IQR或大于Q3 + 1.5 * IQR的值。Q1 = df['A'].quantile(0.25) Q3 = df['A'].quantile(0.75) IQR = Q3 - Q1 lower_bound = Q1 - 1.5 * IQR upper_bound = Q3 + 1.5 * IQR # outliers_iqr = df[(df['A'] < lower_bound) | (df['A'] > upper_bound)]
可视化方法:
df.boxplot() 简直是识别异常值的利器。它能直观地展示数据的分布、中位数、四分位数,以及超出“胡须”范围的离群点(通常就是IQR方法识别的异常值)。业务知识: 这才是最最关键的。一个统计上看起来“异常”的值,在业务逻辑上可能完全合理。比如,一个电商平台某天销售额突然暴涨,可能是因为“双十一”大促,而不是数据错误。脱离业务背景谈异常值处理,往往会犯大错。
处理异常值的方法:
删除:
替换(Winsorization/Capping):
# 将超出上限的异常值替换为上限值 df.loc[df['A'] > upper_bound, 'A'] = upper_bound # 将低于下限的异常值替换为下限值 df.loc[df['A'] < lower_bound, 'A'] = lower_bound
转换:
分箱/离散化:
不处理:
处理异常值是一个迭代的过程,可能需要尝试多种方法,并结合业务专家的意见。重要的是要记住,处理异常值的目的不是为了让数据看起来“完美”,而是为了让数据更好地服务于我们的分析目标。
以上就是Python怎样进行数据清洗?pandas预处理技巧的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号