锋哥原创的Pandas2 Python数据处理与分析 视频教程:
2025版 Pandas2 Python数据处理与分析 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili
数据清洗是数据分析的一个重要步骤,关系到数据的质量,而数据的质量又关系到数据分析的效果。数据清洗一般包括缺失值填充、冗余数据删除、数据格式化、异常值处理、逻辑错误数据检测、数据一致性校验、重复值过滤、数据质量评估等。Pandas提供了一系列操作方法帮助我们轻松完成这些操作。
缺省值处理
1,检测缺省值
isna() 或 isnull(),检测缺失值 (NaN
, None
, NaT
),返回布尔型 DataFrame/Series
示例:
import pandas as pd
import numpy as np
df = pd.DataFrame({
'A': [1, np.nan, 3],
'B': ['x', None, 'z'],
'C': [pd.NaT, pd.Timestamp('2023'), None]
})
# 检测所有缺失值
print(df.isna())
notna() 或 notnull(),检测非缺失值,与 isna() 结果相反
统计缺失值数量
按列统计
print(df.isna().sum())
总体统计
print(df.isna().sum().sum()) # 总缺失值数量
2,删除缺失值
在 Pandas 中,dropna()
是处理缺失值的核心方法,用于删除包含缺失值(NaN
、None
、NaT
)的行或列。以下是详细用法总结,结合场景和代码示例说明:
基本语法:
DataFrame.dropna(
axis=0, # 删除方向:0 或 'index'(行),1 或 'columns'(列)
how='any', # 删除条件:'any'(存在缺失即删),'all'(全为缺失才删)
thresh=None, # 保留非缺失值数量 ≥ thresh 的行/列
subset=None, # 指定检查缺失值的列/行子集
inplace=False # 是否原地修改(不返回新对象)
)
我们看一个示例:
import pandas as pd
import numpy as np
data = {
'A': [1, np.nan, 3, 4],
'B': [np.nan, 5, None, 7],
'C': ['x', 'y', np.nan, 'z']
}
df = pd.DataFrame(data)
print("原始数据:")
print(df)
删除缺失值行,保留非缺失值数量大于等于2.
df.dropna(thresh=2)
3,填充缺失值
缺失值填充,我们用fillna()方法,前面已经介绍过。
处理重复值
检测重复行
在 Pandas 中,duplicated()
是用于检测 DataFrame 或 Series 中重复行或元素的核心方法。它返回一个布尔值序列,标记重复项(True
表示重复)。以下是详细用法说明,结合代码示例和场景分析:
基本语法:
DataFrame.duplicated(
subset=None, # 指定判断重复的列(默认所有列)
keep='first', # 标记策略:'first'(默认保留第一个),'last'(保留最后一个),False(全标记为重复)
inplace=False # 是否原地修改(无返回值,仅适用于某些操作,通常不用于此方法)
)
示例:
数据准备:
import pandas as pd
data = {
'ID': [101, 102, 103, 101, 102],
'Name': ['Alice', 'Bob', 'Charlie', 'Alice', 'Bob'],
'Score': [85, 90, 95, 85, 90]
}
df = pd.DataFrame(data)
print("原始数据:")
print(df)
检测所有列完全重复的行。
df.duplicated()
删除重复行
在 Pandas 中,drop_duplicates()
是用于删除 DataFrame 或 Series 中重复行的核心方法。它基于用户定义的规则(如保留首个或末个重复项、指定判断重复的列等)清理数据。以下是详细用法说明,结合代码示例和场景分析:
基本语法:
DataFrame.drop_duplicates(
subset=None, # 指定判断重复的列(默认所有列)
keep='first', # 保留策略:'first'(保留第一个重复项)、'last'(保留最后一个)、False(删除所有重复项)
inplace=False, # 是否直接修改原对象(不返回新对象)
ignore_index=False # 是否重置删除后的索引(默认保持原索引)
)
示例:
df.drop_duplicates()
数据类型转换
数据类型转换用astype()和to_numeric()这些方法,前面已经介绍过。
字符串处理
核心方法(通过 .str
访问器):
-
清洗与转换:
df['列名'].str.strip() # 去除两端空格 df['列名'].str.lower() # 转为小写 df['列名'].str.upper() # 转为大写 df['列名'].str.replace('old', 'new') # 替换字符
-
分割与合并:
df['列名'].str.split(',', expand=True) # 分割为多列(返回 DataFrame) df['合并列'] = df['列1'].str.cat(df['列2'], sep='-') # 合并两列
-
正则表达式:
df['列名'].str.extract(r'(\d+)') # 提取数字 df['列名'].str.contains(r'^A', na=False) # 检查是否以 A 开头(处理缺失值)
数据合并
前面已经讲过。
数据筛选
条件筛选
-
多条件组合:
df[(df['A'] > 10) & (df['B'] == 'X')] # 且(and) df[(df['A'] > 10) | (df['B'] == 'X')] # 或(or) df[~df['B'].isin(['X', 'Y'])] # 非(not in)
-
query 方法:
df.query('A > 10 and B == "X"') # 更简洁的条件表达式
按位置筛选
-
loc 和 iloc:
df.loc[df['A'] > 10, ['B', 'C']] # 筛选行,选择 B、C 列 df.iloc[0:5, [1, 2]] # 前5行,第2、3列
数据分组与聚合
-
单列聚合:
df.groupby('分组列')['数值列'].agg(['sum', 'mean', 'max'])
-
多列不同聚合方式:
df.groupby('分组列').agg({ '数值列1': 'sum', '数值列2': lambda x: x.mean() * 100 })
异常值处理
统计方法识别
-
Z-Score 法:Z-Score(标准分数)是一种统计学方法,用于衡量数据点与数据集均值的偏离程度,以标准差为单位。它在数据预处理(如异常值检测、数据标准化)中广泛应用,尤其在机器学习和数据分析中常用于数据规范化。
z_scores = (df['列名'] - df['列名'].mean()) / df['列名'].std() df = df[z_scores.abs() < 3] # 删除 Z 值绝对值大于3的异常值
-
IQR 法:IQR 法(四分位距法,Interquartile Range)是一种基于数据分位数的异常值检测方法,适用于识别数据中的极端值,尤其对非正态分布数据(如偏态分布)具有更强的鲁棒性。它通过计算数据的四分位距(IQR)来确定正常值的范围,超出此范围的数据点被视为异常值。
Q1 = df['列名'].quantile(0.25) Q3 = df['列名'].quantile(0.75) IQR = Q3 - Q1 df = df[(df['列名'] >= Q1 - 1.5*IQR) & (df['列名'] <= Q3 + 1.5*IQR)]
替换异常值
df.loc[df['列名'] > 1000, '列名'] = 1000 # 将超过1000的值截断为1000
列操作和重命名
添加新列:
df['新列'] = df['列1'] + df['列2']
df['新列'] = np.where(df['列名'] > 100, '高', '低') # 条件赋值
删除列:
df.drop(['列1', '列2'], axis=1, inplace=True)
重命名:
df.rename(columns={'旧列名': '新列名'}, inplace=True)
索引操作
-
设置索引:
df.set_index('日期列', inplace=True) # 将日期列设为索引
-
重置索引:
df.reset_index(drop=True, inplace=True) # 删除原索引
完整数据清洗示例
test.data.csv
ID,Name,Age,Gender,Department,Salary,HireDate
1,Alice,28,F,HR,55000,2023-01-15
2,Bob,32,M,IT,65000,2023-02-20
3,Charlie,,M,IT,,2023-03-05
4,David,45,M,Finance,75000,2023-04-10
5,Eve,22,F,HR,48000,2023-05-12
6,Frank,38,M,IT,82000,2023-06-18
7,Grace,29,F,Marketing,63000,2023-07-25
8,Heidi,35,F,Finance,,2023-08-30
9,Ivan,41,M,IT,71000,2023-09-14
10,Judy,33,F,HR,59000,2023-10-22
11,Alex,25,M,IT,150000,2023-11-05
12,Sam,27,F,Marketing,18000,2023-12-10
测试代码:
import pandas as pd
def load_data(file_path):
"""加载 CSV 数据"""
try:
return pd.read_csv(file_path)
except FileNotFoundError:
print(f"错误: 文件 '{file_path}' 不存在")
return None
def clean_data(df):
"""清洗数据"""
if df is None:
return None
# 处理缺失值
print("处理缺失值...")
df = df.dropna(subset=['Name']) # 删除 Name 列中的缺失值
df['Age'] = df['Age'].fillna(df['Age'].median()) # 用中位数填充 Age 列
df['Salary'] = df['Salary'].fillna(df['Salary'].mean()) # 用均值填充 Salary 列
# 处理重复值
print("处理重复值...")
duplicates = df.duplicated().sum()
if duplicates > 0:
df = df.drop_duplicates()
print(f"已删除 {duplicates} 个重复行")
# 处理异常值
print("处理异常值...")
Q1 = df['Salary'].quantile(0.25)
Q3 = df['Salary'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
df = df[(df['Salary'] >= lower_bound) & (df['Salary'] <= upper_bound)]
# 数据类型转换
print("数据类型转换...")
df['HireDate'] = pd.to_datetime(df['HireDate'])
return df
def main():
input_file = 'test_data.csv'
output_file = 'cleaned_data.csv'
# 加载数据
df = load_data(input_file)
if df is None:
return
print("原始数据基本信息:")
df.info()
# 数据清洗
cleaned_df = clean_data(df)
# 保存结果
if cleaned_df is not None:
cleaned_df.to_csv(output_file, index=False)
print(f"清洗后的数据已保存到 {output_file}")
print("清洗后数据基本信息:")
cleaned_df.info()
if __name__ == "__main__":
main()