Pandas实战 DataFrame数据处理、清洗与统计分析全解析
Pandas是Python数据处理领域的核心库,而DataFrame作为其核心数据结构,是处理结构化数据的必备工具。本文从实际业务场景出发,详解DataFrame的基础操作、数据清洗核心方法和统计分析技巧,内容覆盖新手入门到实战应用,帮助你高效处理各类数据问题。
一、环境准备与DataFrame基础
1. 安装与导入
首先确保安装了Pandas库,建议搭配NumPy使用(数据计算更高效):
pip install pandas numpy
导入常用库:
import pandas as pd
import numpy as np
2. 创建DataFrame
DataFrame可理解为“带标签的二维表格”,支持从列表、字典、CSV/Excel文件等多种方式创建,以下是最常用的场景:
# 1. 从字典创建(最常用)
data = {
"姓名": ["张三", "李四", "王五", "赵六"],
"年龄": [25, 32, 28, np.nan], # 包含缺失值
"城市": ["北京", "上海", "广州", "北京"],
"月薪": [8000, 12000, 9500, 15000]
}
df = pd.DataFrame(data)
# 2. 从CSV文件读取(实战核心)
# df = pd.read_csv("data.csv", encoding="utf-8")
# 3. 从Excel文件读取
# df = pd.read_excel("data.xlsx", sheet_name="Sheet1")
# 查看数据基本信息
print("数据前3行:")
print(df.head(3)) # 查看前n行,默认5行
print("\n数据维度:", df.shape) # (行数, 列数)
print("\n数据类型:")
print(df.dtypes)
print("\n数据概览:")
print(df.info()) # 含非空值数量、数据类型等关键信息
3. 基础索引与筛选
快速定位和提取目标数据是DataFrame的基础能力,掌握以下操作可解决80%的基础筛选需求:
# 1. 按列名提取列
name_series = df["姓名"] # 单列,返回Series
name_salary_df = df[["姓名", "月薪"]] # 多列,返回DataFrame
# 2. 按行筛选(布尔索引)
# 筛选月薪大于10000的行
high_salary_df = df[df["月薪"] > 10000]
# 筛选北京地区且年龄小于30的行
beijing_young_df = df[(df["城市"] == "北京") & (df["年龄"] < 30)]
# 3. 按位置筛选(iloc)
first_row = df.iloc[0] # 第一行
col_2_to_3 = df.iloc[:, 1:3] # 第2-3列(所有行)
# 4. 按标签筛选(loc,需设置索引)
df_index = df.set_index("姓名")
li_salary = df_index.loc["李四", "月薪"] # 李四的月薪
二、DataFrame数据清洗(实战核心)
真实数据往往存在缺失值、重复值、异常值,数据清洗是分析前的关键步骤,直接影响分析结果的准确性。
1. 缺失值处理
缺失值(NaN)是最常见的问题,需根据业务场景选择删除、填充或插值:
# 1. 查看缺失值
print("缺失值统计:")
print(df.isnull().sum()) # 按列统计缺失值数量
# 2. 删除缺失值(适用于缺失率低的情况)
df_drop = df.dropna() # 删除所有含缺失值的行
# df_drop_col = df.dropna(axis=1) # 删除含缺失值的列
# df_drop_thresh = df.dropna(thresh=3) # 保留至少3个非空值的行
# 3. 填充缺失值(更常用)
df_fill = df.copy()
# 数值型列用均值填充
df_fill["年龄"] = df_fill["年龄"].fillna(df_fill["年龄"].mean())
# 分类列用众数填充
df_fill["城市"] = df_fill["城市"].fillna(df_fill["城市"].mode()[0])
# 用指定值填充
df_fill["月薪"] = df_fill["月薪"].fillna(0)
# 4. 插值填充(适用于时序数据)
# df_fill["年龄"] = df_fill["年龄"].interpolate() # 线性插值
2. 重复值处理
重复数据会导致统计结果偏差,需先检测再删除:
# 1. 检测重复行
print("重复行数量:", df.duplicated().sum())
# 检测指定列的重复(如姓名+城市重复)
print("指定列重复数:", df.duplicated(subset=["姓名", "城市"]).sum())
# 2. 删除重复行
df_drop_dup = df.drop_duplicates() # 删除完全重复的行
# 保留第一次出现的重复行(默认),保留最后一次用keep="last"
df_drop_dup_subset = df.drop_duplicates(subset=["姓名"], keep="first")
3. 异常值处理
异常值(如月薪为负数、年龄超过100)需识别并处理,常用方法为箱线图检测或3σ原则:
# 方法1:箱线图检测(可视化)
import matplotlib.pyplot as plt
plt.boxplot(df["月薪"])
plt.title("月薪箱线图(识别异常值)")
plt.show()
# 方法2:3σ原则(适用于正态分布数据)
def remove_outliers(df, col):
mean = df[col].mean()
std = df[col].std()
# 筛选在3个标准差内的数据
df_clean = df[(df[col] > mean - 3*std) & (df[col] < mean + 3*std)]
return df_clean
df_salary_clean = remove_outliers(df, "月薪")
# 方法3:替换异常值(用中位数)
q1 = df["月薪"].quantile(0.25) # 下四分位数
q3 = df["月薪"].quantile(0.75) # 上四分位数
iqr = q3 - q1 # 四分位距
# 异常值阈值
lower_bound = q1 - 1.5*iqr
upper_bound = q3 + 1.5*iqr
# 替换超出阈值的值为中位数
df["月薪"] = np.where(
(df["月薪"] < lower_bound) | (df["月薪"] > upper_bound),
df["月薪"].median(),
df["月薪"]
)
4. 数据格式与类型清洗
# 1. 列类型转换
df["年龄"] = df["年龄"].astype("float64") # 转为浮点型
df["月薪"] = df["月薪"].astype("int64") # 转为整型
df["入职时间"] = pd.to_datetime(df["入职时间"], format="%Y-%m-%d") # 转为日期型
# 2. 字符串清洗(如城市列去空格、统一大小写)
df["城市"] = df["城市"].str.strip() # 去除首尾空格
df["城市"] = df["城市"].str.replace("北京市", "北京") # 替换字符
df["姓名"] = df["姓名"].str.upper() # 转为大写
# 3. 列名规范化
df.rename(columns={"姓名": "name", "年龄": "age"}, inplace=True) # 重命名列
df.columns = df.columns.str.lower() # 列名转为小写
三、DataFrame统计分析(业务实战)
数据清洗完成后,可通过统计分析挖掘数据价值,以下是最常用的分析方法。
1. 基础描述性统计
快速获取数据的集中趋势、离散程度等核心指标:
# 整体描述统计(仅数值型列)
print("基础统计指标:")
print(df.describe())
# 单独统计指标
print("月薪均值:", df["月薪"].mean())
print("年龄中位数:", df["年龄"].median())
print("城市众数:", df["城市"].mode()[0])
print("月薪标准差:", df["月薪"].std())
print("月薪最大值/最小值:", df["月薪"].max(), "/", df["月薪"].min())
print("月薪分位数:", df["月薪"].quantile([0.25, 0.5, 0.75]))
# 分类列统计
print("各城市人数:")
print(df["城市"].value_counts()) # 计数
print("各城市占比:")
print(df["城市"].value_counts(normalize=True) * 100) # 占比(百分比)
2. 分组统计(groupby)
按分类字段聚合分析,是业务分析的核心操作:
# 按城市分组,统计月薪的均值、总和、数量
city_salary = df.groupby("城市")["月薪"].agg(["mean", "sum", "count"])
print("各城市月薪统计:")
print(city_salary)
# 多字段分组+多指标聚合
city_age_salary = df.groupby(["城市", "年龄"])["月薪"].agg({
"月薪均值": "mean",
"月薪最大值": "max",
"人数": "count"
}).reset_index()
print("各城市各年龄段月薪统计:")
print(city_age_salary)
# 分组后筛选(如筛选人数大于1的城市)
city_filter = df.groupby("城市").filter(lambda x: len(x) > 1)
3. 透视表与交叉表
透视表(pivot_table)是分组统计的可视化形式,交叉表(crosstab)适用于分类变量分析:
# 透视表:行=城市,列=年龄段,值=月薪,聚合方式=均值
df["年龄段"] = pd.cut(df["年龄"], bins=[20, 25, 30, 35], labels=["20-25", "25-30", "30-35"])
pivot_df = pd.pivot_table(
df,
values="月薪",
index="城市",
columns="年龄段",
aggfunc="mean",
fill_value=0 # 缺失值填充为0
)
print("各城市各年龄段月薪透视表:")
print(pivot_df)
# 交叉表:统计各城市各年龄段的人数
cross_df = pd.crosstab(df["城市"], df["年龄段"], margins=True) # margins=True显示总计
print("各城市各年龄段人数交叉表:")
print(cross_df)
4. 相关性分析
分析数值型变量间的线性关系,常用皮尔逊相关系数:
# 计算相关性矩阵
corr_matrix = df[["年龄", "月薪"]].corr()
print("相关性矩阵:")
print(corr_matrix)
# 可视化相关性(热力图)
import seaborn as sns
sns.heatmap(corr_matrix, annot=True, cmap="coolwarm", fmt=".2f")
plt.title("年龄与月薪相关性热力图")
plt.show()
5. 数据排序与排名
# 按月薪降序排序
df_sorted = df.sort_values(by="月薪", ascending=False)
# 按城市升序、年龄降序排序
df_sorted_multi = df.sort_values(by=["城市", "年龄"], ascending=[True, False])
# 月薪排名(ascending=False表示降序,dense表示密集排名)
df["月薪排名"] = df["月薪"].rank(method="dense", ascending=False)
四、实战案例:员工薪资数据分析
结合以上知识点,完成一个完整的分析流程:
# 1. 读取数据
df = pd.read_csv("employee_salary.csv", encoding="utf-8")
# 2. 数据清洗
# 处理缺失值
df["年龄"] = df["年龄"].fillna(df["年龄"].median())
df["部门"] = df["部门"].fillna("未知")
# 删除重复行
df = df.drop_duplicates(subset=["员工编号"])
# 处理异常值(月薪小于0或大于10万为异常)
df.loc[(df["月薪"] < 0) | (df["月薪"] > 100000), "月薪"] = df["月薪"].median()
# 3. 统计分析
# 各部门薪资均值、中位数
dept_salary = df.groupby("部门")["月薪"].agg(["mean", "median"]).round(2)
print("各部门薪资统计:")
print(dept_salary)
# 各城市薪资TOP10
city_top10 = df.groupby("城市")["月薪"].nlargest(10).reset_index()
print("\n各城市薪资TOP10:")
print(city_top10)
# 年龄与月薪的相关性
corr = df[["年龄", "月薪"]].corr().iloc[0, 1].round(2)
print(f"\n年龄与月薪的相关系数:{corr}")
# 4. 结果导出
dept_salary.to_excel("各部门薪资统计.xlsx", index=True)

浙公网安备 33010602011771号