文章比较干,请备好水再看
今天,咱们不讲大道理,直接来点实战------教大家如何从0到1搞定Pandas数据分析的全流程!开干,咱玩的就是真实!

1. 数据导入------把"脏数据"请进来
首先得把数据请进来。数据来源可能是CSV、Excel,甚至数据库。这里咱们就直接模拟生成一份数据,数据里面充满了各种"坑":
python
import pandas as pd
import numpy as np
# 模拟生成数据(注意:这里故意加了缺失值、异常值、重复数据以及格式混乱的日期)
data = {
"姓名": ["张三", "李四", "王五", "赵六", "小明", "小红", "老王", "张三", "赵六"],
"年龄": [25, 30, 22, np.nan, 29, 26, 28, 25, 200], # 缺失值 & 异常值
"工龄": [2, 5, 1, 8, np.nan, 3, -1, 2, 10], # 缺失值 & 错误数据(负数)
"薪资": [8000, 12000, 6000, 15000, 10000, 9000, 8500, 8000, 16000], # 重复行
"入职日期": ["2022-06-01", "2020/05/15", "2021-09-10", "2019-12-01",
"2023/01/01", "2021-08-15", "2018-03-10", "2022-06-01", "2019-12-01"], # 日期格式混乱
"部门": ["市场部", "技术部", "市场部", "技术部", "市场部", "人事部", "技术部", "市场部", "财务部"]
}
df = pd.DataFrame(data)
print("导入数据:\n", df)

以下帮大家简单给出几个读取Excel、csv、数据库的示例代码,方便新手也能快速上手:
读取CSV文件
python
import pandas as pd
# 读取CSV文件(确保data.csv文件在当前目录下)
df_csv = pd.read_csv('data.csv')
print("CSV数据预览:")
print(df_csv.head())
说明 :pd.read_csv()
非常好用,直接加载CSV数据。记得检查文件路径哦~
读取Excel文件
python
import pandas as pd
# 读取Excel文件的第一个工作表
df_excel = pd.read_excel('data.xlsx', sheet_name='Sheet1')
print("Excel数据预览:")
print(df_excel.head())
说明 :pd.read_excel()
可以指定工作表名(或索引)。
从数据库读取数据
这里用SQLAlchemy作为数据库引擎示例,假设你使用的是SQLite数据库(其他数据库类似,只需更换连接字符串)。
python
import pandas as pd
from sqlalchemy import create_engine
# 创建数据库引擎(这里使用SQLite数据库,数据库文件为mydatabase.db)
engine = create_engine('sqlite:///mydatabase.db')
# 编写SQL查询语句
query = "SELECT * FROM table_name"
# 读取数据库中的数据
df_db = pd.read_sql(query, engine)
print("数据库数据预览:")
print(df_db.head())
说明 :pd.read_sql()
可以直接执行SQL语句,将查询结果转成DataFrame,超方便!💡
2. 数据清洗🛁
数据清洗其实就是对症下药,让数据变得干净、标准,便于后续处理。这里主要包括:
2.1 缺失值处理
首先看看哪些地方数据"不完整":
python
print("缺失值统计:\n", df.isnull().sum())
go
缺失值统计:
姓名 0
年龄 1
工龄 1
薪资 0
入职日期 0
部门 0
dtype: int64
通过缺失值统计可以发现年龄和工龄2列分别有1个缺失值。
处理策略:
年龄
缺失值用中位数填充(受极端值影响小)工龄
缺失值用部门内均值补全(让每个部门的数据更有说服力)
python
df["年龄"]=df["年龄"].fillna(df["年龄"].median())
df["工龄"]=df["工龄"].fillna(df.groupby("部门")["工龄"].transform("mean"))

我们可以看到赵六 缺失的年龄和小明缺失的工龄已经按照处理策略进行了填充。
在实际数据分析中,缺失值(NaN)是最常见的问题。处理方式一般取决于业务需求和数据特点。以下是常见的缺失值处理策略,以及适用场景:
🌟 2.1.1 删除缺失值
适用于:
- 缺失值占比极少(比如 < 5%)
- 该列不是关键数据
- 业务可以接受少量数据丢失
示例:
python
import pandas as pd
df = pd.DataFrame({
'姓名': ['张三', '李四', '王五', None, '赵六'],
'年龄': [23, 25, None, 30, 28],
'薪资': [5000, 7000, None, 8000, 9000]
})
df_dropna = df.dropna() # 删除含缺失值的行
print(df_dropna)
变体:
df.dropna(subset=['某列'])
只删除特定列缺失的行df.dropna(axis=1)
删除含缺失值的列(谨慎使用)
💡 2.1.2 用特定值填充
适用于:
- 缺失值占比较高,但可以用默认值替代
- 比如:填充 0(财务数据)、填充 "未知"(分类数据)
示例:
python
df_filled = df.fillna({'姓名': '未知', '年龄': df['年龄'].mean(), '薪资': 0})
print(df_filled)
解释:
df.fillna(value)
可用于填充缺失值df['某列'].mean()
用该列均值填充(适用于数值数据)df['某列'].median()
用中位数填充,适用于受极端值影响的数据df['某列'].mode()[0]
用众数填充(适用于分类变量)
🔁 2.1.3 插值填充
适用于:
- 时间序列数据,可以用前后数据预测缺失值
示例:
python
df_interpolated = df.interpolate()
print(df_interpolated)
解释:
interpolate()
采用线性插值法填充数值缺失值(适用于趋势平稳的数据)
📊 2.1.4 前向/后向填充
适用于:
- 时间序列数据,如股票价格、天气数据等
示例:
python
df_ffill = df.ffill() # 前向填充(用前一行数据填充)
df_bfill = df.bfill() # 后向填充(用后一行数据填充)
⚠️ 注意:
- 适用于有逻辑顺序的数据(如日期、时间)
- 如果缺失值连续过多,效果可能不佳
🎯 2.1.5 机器学习模型预测填充
适用于:
- 缺失值较多且无法简单填充
- 需要更精确地估计缺失值,如回归预测缺失数值、分类模型预测缺失类别
示例(简单回归填充):
python
from sklearn.impute import SimpleImputer
import numpy as np
imputer = SimpleImputer(strategy='mean') # 也可以换成 'median' 或 'most_frequent'
df['年龄'] = imputer.fit_transform(df[['年龄']])
高级方法:
- 使用
KNNImputer
(基于最近邻填充) - 用
RandomForestRegressor
或XGBoost
预测缺失值
总之一切要根据业务场景来处理,拒绝🙅无脑 fillna(0)
!
2.2 异常值处理
异常值处理也是数据分析中最常见的场景了。比如200岁的"长生不老者"或负数工龄:
python
# 年龄异常值处理:用箱线图法(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 = df[df["工龄"] >= 0]
在实际工作中,处理异常值的方式取决于业务需求、数据类型和分析目标。以下是常见的异常值处理策略,每种方法都附带 适用场景 !🎯
🔍 2.2.1 直接删除异常值
适用于:
- 异常值是明显的错误数据,例如年龄 = 200、工资 = -5000
- 异常值数量较少,删除不会影响整体分析
示例:(删除年龄超过 100 岁的异常数据)
python
import pandas as pd
df = pd.DataFrame({'姓名': ['张三', '李四', '王五', '赵六'], '年龄': [25, 30, 150, 28]})
df_filtered = df[df['年龄'] < 100] # 只保留年龄小于100的数据
print(df_filtered)
变体:
df.drop(df[df['某列'] > 阈值].index, inplace=True)
适用于多个条件删除
📊 2.2.2 用统计方法识别异常值
📌 方法 1:基于均值和标准差(3σ 法则)
适用于:
- 数据服从正态分布
- 适用于数值型数据,如薪资、身高、体重
原理:
如果数据服从正态分布,99.7% 的数据应该在 均值 ± 3*标准差
之间,超出范围的可以认为是异常值。
python
import numpy as np
# 生成示例数据
df = pd.DataFrame({'工资': [5000, 5500, 7000, 9000, 20000]})
mean = df['工资'].mean()
std = df['工资'].std()
# 3σ 规则
df_filtered = df[(df['工资'] > mean - 3 * std) & (df['工资'] < mean + 3 * std)]
print(df_filtered)
⚠️ 注意:
- 该方法适用于正态分布数据,但如果数据偏态(如工资通常是右偏的),就不适用了。
📌 方法 2:基于 IQR(四分位数法) 适用于:
- 数据不一定服从正态分布
- 适用于房价、工龄等非对称数据
原理:
IQR(四分位距)= Q3(75% 分位数)- Q1(25% 分位数),通常认为超出1.5 倍 IQR 的数据是异常值。
python
# 计算四分位数
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_filtered = df[(df['工资'] >= lower_bound) & (df['工资'] <= upper_bound)]
print(df_filtered)
✅ 优点 :适用于偏态数据,不受极端值影响。
⚠️ 缺点:如果数据本身就有很大波动,可能会误删正常数据。
🔄 2.2.3 替换异常值
适用于:
- 异常值较多,不宜直接删除
- 业务允许用合适的统计值替换异常值
(1)用均值/中位数替换
python
median = df['工资'].median()
df.loc[df['工资'] > upper_bound, '工资'] = median
df.loc[df['工资'] < lower_bound, '工资'] = median
💡 适用于:异常值较少,且数据对极端值不敏感时。
(2)用前一个或后一个值填充
适用于:
- 时间序列数据(如股票价格、气温等)
- 异常值是偶然波动造成的
python
df['工资'] = df['工资'].replace(df['工资'][df['工资'] > upper_bound], method='ffill') # 用前一个值填充
📈 2.2.4 使用机器学习模型检测异常值
适用于:
- 数据分布复杂,难以手动设置阈值
- 对异常值检测要求高
(1)使用 Isolation Forest
识别异常值
python
from sklearn.ensemble import IsolationForest
model = IsolationForest(contamination=0.05) # 设定异常值比例 5%
df['is_outlier'] = model.fit_predict(df[['工资']])
# 过滤掉异常值
df_filtered = df[df['is_outlier'] == 1]
print(df_filtered)
💡 适用于:高维数据、非线性数据,如信用卡欺诈检测。
🚀 2.2.5 分箱处理异常值
适用于:
- 异常值是业务逻辑上的"极端值"
- 比如年龄 80 岁以上算"高龄",可以归类到"老年"
python
df['工资等级'] = pd.cut(df['工资'], bins=[0, 5000, 10000, 20000], labels=['低', '中', '高'])
print(df)
💡 适用于:工资、年龄、分数等有固定区间的数据。
2.3 重复值处理
重复数据?老板说数据要"一丝不苟",咱们就把重复的记录给"去水分"了:
python
df.drop_duplicates(inplace=True)
当然在实际工作中,重复数据不能上来就给老板删掉,还是要结合业务场景。以下是常见的重复值处理策略!
🔍 2.3.1 检查数据中是否存在重复值
在处理之前,先检查是否有重复值:
python
import pandas as pd
df = pd.DataFrame({
'姓名': ['张三', '李四', '王五', '张三', '赵六'],
'年龄': [25, 30, 35, 25, 28],
'薪资': [5000, 7000, 9000, 5000, 8000]
})
# 检查数据是否存在重复值
print(df.duplicated()) # 返回布尔值,每行为 True 表示该行是重复的
print(df.duplicated().sum()) # 统计重复行的个数
✅ df.duplicated()
默认检查整行是否完全相同。
🗑️ 2.3.2 删除重复值
适用于:
- 重复数据是明显的错误数据
- 不会影响业务逻辑
python
df_no_duplicates = df.drop_duplicates()
print(df_no_duplicates)
⚠️ 注意:
drop_duplicates()
默认删除完全重复的行,保留第一条drop_duplicates(keep='last')
保留最后一条drop_duplicates(keep=False)
删除所有重复项
🎯 只针对某几列去重
如果某些列重复,而其他列不重要,可以指定列去重:
python
df_no_duplicates = df.drop_duplicates(subset=['姓名'])
💡 适用于: 去重时只关心某些关键字段,比如手机号、订单号等。
📊 2.3.3 标记重复值而不删除
适用于:
- 想要保留重复数据,但标记出来方便分析
python
df['是否重复'] = df.duplicated()
df['是否重复_保留第一条'] = df.duplicated(keep='first')
df['是否重复_保留最后一条'] = df.duplicated(keep='last')
print(df)
✅ 适用于数据质量检查,可以筛选出来进一步分析。
🔄 2.3.4 合并重复数据
适用于:
- 同一个实体存在多条记录,但信息不完整
- 希望合并信息,而不是简单删除
(1)使用 groupby
合并
python
df_grouped = df.groupby('姓名', as_index=False).agg({
'年龄': 'first', # 取第一条记录的年龄
'薪资': 'mean' # 计算平均薪资
})
print(df_grouped)
💡 适用于:
- 客户信息合并(如同一个手机号多次注册)
- 订单数据合并(如同一客户多次购买)
(2)用 fillna()
合并缺失值
如果多条重复数据中某些字段为空,可以合并补全:
python
df_filled = df.groupby('姓名', as_index=False).first() # 保留第一条完整数据
print(df_filled)
✅ 适用于补全客户、产品信息等场景。
🎭 2.3.5 处理轻微重复(模糊去重)
适用于:
- 数据不完全相同,但本质是同一个实体
- 比如姓名错别字、邮箱格式不同等
(1)去掉首尾空格
python
df['姓名'] = df['姓名'].str.strip()
(2)大小写统一
python
df['姓名'] = df['姓名'].str.lower()
(3)模糊匹配去重(fuzzywuzzy
)
适用于:
- 姓名、公司名称等可能有轻微差异
python
from fuzzywuzzy import process
name_list = df['姓名'].tolist()
match = process.extract('张三', name_list, limit=3) # 找到最相似的3个名字
print(match)
✅ 适用于客户数据、企业名称等可能存在拼写差异的场景。
2.4 日期格式统一
日期格式乱七八糟?别慌,Pandas自带神仙函数来拯救:
python
# 适用于日期分隔符不同的情况(/、-、.)
df['入职日期'] = df['入职日期'].str.replace(r'[/.-]', '-', regex=True) # 统一为 "YYYY-MM-DD"
df['入职日期'] = pd.to_datetime(df['入职日期'], errors='coerce') # 解析日期
到这一步,数据清理就搞定了!
3. 数据处理与转换------给数据穿上漂亮的"外衣"
数据清洗完后,我们常常需要对数据进行一些转换,方便后续分析。比如对数值型数据进行归一化、对类别数据进行编码,或创建一些新的特征。
3.1 数据类型转换
确保每列数据都是你预期的类型,这样在做数值计算和统计时才不会出岔子:
python
df["年龄"] = df["年龄"].astype(int)
df["工龄"] = df["工龄"].astype(int)
3.2 新特征生成
有时候你会想知道每个人的"经验指数",简单来说就是工龄与年龄的比值,顺便让数据更有看头:
python
df["经验指数"] = df["工龄"] / df["年龄"]
这样,数据不仅干净,还穿上了漂亮的新装,等待你去探索!
4. 数据探索与分析------让数据自己"说话" 📊
这一步可是重头戏!数据探索需要结合统计方法和业务背景,找出数据背后的秘密。作为专业人士,我们要做到以下几点:
4.1 描述性统计
通过基本统计量了解数据的分布和趋势:
python
print("数据描述性统计:\n", df.describe())
4.2 部门薪资分析
分析不同部门的薪资分布,不仅能看出部门间的差距,也能发现数据中的潜在问题,比如是否存在薪资异常或数据偏态现象。
python
# 按部门统计平均薪资和薪资中位数
dept_salary_stats = df.groupby("部门")["薪资"].agg(["mean", "median"])
print("各部门薪资统计:\n", dept_salary_stats)
专业点拨:
- 均值受极端值影响较大,而中位数更稳健
- 如果两者差距较大,可能暗示数据中存在异常值或偏态分布
4.3 工龄与薪资关系
探讨工龄对薪资的影响,利用散点图和回归分析帮助我们发现趋势:
python
import seaborn as sns
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.figure(figsize=(8, 5))
sns.regplot(x="工龄", y="薪资", data=df, scatter_kws={"s": 50}, line_kws={"color": "red"})
plt.title("工龄与薪资的关系")
plt.xlabel("工龄")
plt.ylabel("薪资")
plt.show()

专业点拨:
- 观察散点图中数据点的分布,可以判断是否存在线性关系
- 适当加入回归线可以帮助我们更直观地理解趋势和波动
4.4 经验指数解读
用"经验指数"来评估员工的成长与稳定性,这一指标能帮助HR判断哪些员工既有潜力又稳扎稳打:
python
plt.figure(figsize=(8, 5))
sns.boxplot(x="部门", y="经验指数", data=df)
plt.title("各部门经验指数分布")
plt.xlabel("部门")
plt.ylabel("经验指数")
plt.show()
这一步,不仅是数据分析,更像是给数据做一次"全身检查",发现每个细节问题,让决策者有据可依!

5. 数据可视化------把分析结果变成"图说故事" 🎨
数据可视化能让我们的分析结果更直观,也更容易与非技术同事沟通。这里再展示几个常用的可视化手段:
5.1 部门薪资箱线图
直观展示不同部门薪资的分布及异常值:
python
plt.figure(figsize=(8, 5))
sns.boxplot(x="部门", y="薪资", data=df)
plt.title("各部门薪资箱线图")
plt.xlabel("部门")
plt.ylabel("薪资")
plt.show()

5.2 平均薪资柱状图
用柱状图展示各部门平均薪资,让数据更"高大上":
python
avg_salary = df.groupby("部门")["薪资"].mean().reset_index()
plt.figure(figsize=(8, 5))
sns.barplot(x="部门", y="薪资", data=avg_salary)
plt.title("各部门平均薪资")
plt.xlabel("部门")
plt.ylabel("平均薪资")
plt.show()

5.3 多变量关联图
综合展示工龄、薪资与部门之间的关系,适合对数据做多角度解读:
python
plt.figure(figsize=(8, 5))
sns.scatterplot(x="工龄", y="薪资", hue="部门", size="经验指数", data=df, sizes=(50, 200))
plt.title("工龄、薪资及经验指数多变量关联图")
plt.xlabel("工龄")
plt.ylabel("薪资")
plt.show()

这些图表不仅让数据"活"起来,还能迅速传达关键信息,让数据决策不再枯燥。
6. 结果输出------把成果交给决策者 📤
分析完数据,最后一步就是输出结果,为业务决策提供支持。常见做法包括生成报告、保存清洗后的数据文件,或者构建交互式仪表盘。
6.1 输出清洗后的数据
python
# 将处理后的数据保存为CSV文件,方便后续使用
df.to_csv("cleaned_data.csv", index=False)
print("清洗后的数据已保存!")
6.2 生成分析报告
把关键统计量、图表和结论整合到报告中,可以用Jupyter Notebook导出HTML,或者用其他BI工具制作仪表盘。这样,老板一看就能知道咱们做了哪些功课!
总结
🎉 今天我们从数据导入、清洗、处理与转换,到数据探索与专业分析,再到可视化和结果输出,走了一遍完整的Pandas数据分析全流程。
- 数据清洗:补缺、剔除异常、去重复,让数据变得标准可靠
- 数据处理与转换:类型转换、新特征生成,为深度分析打下基础
- 数据探索与分析:用描述统计、分组对比和回归分析,找出数据背后的规律
- 数据可视化:多种图表助力,让复杂数据变得一目了然
- 结果输出:把成果整理成报告,给决策者一份专业的"数据药方"
顺手点赞 + 在看,就是对花姐最大的支持!