☰
Pandas数据分析实战:从数据清洗到可视化的完整指南
2026/10/23 12:41:22 网站建设 项目流程

1. 为什么要学 Pandas:数据分析的起点

在做数据分析之前,很多人的第一反应是打开 Excel。Excel 确实足够直观,但当数据量达到几十万行、几百万行,或者需要重复执行清洗、汇总、关联操作时,Excel 就会变得力不从心。这时候,Pandas 就是 Python 生态里最核心的数据分析利器。

Pandas 是一个基于 Python 的开源数据分析库,名字来源于“Panel Data”(面板数据)。它提供了两类核心数据结构:Series(一维)和DataFrame(二维)。借助这两个结构,你可以完成数据读取、清洗、转换、聚合、可视化等一系列操作。

在实际开发中,Pandas 常见的应用场景包括:

  • 数据清洗:处理缺失值、重复值、异常值。
  • 数据转换:类型转换、字段抽取、分箱、归一化。
  • 数据聚合:分组统计、透视表、多表关联。
  • 数据输出:把处理结果导出为 Excel、CSV、数据库表。
  • 与机器学习联动:为 sklearn、XGBoost 等模型准备训练数据。

本文会围绕一套“由浅入深”的学习路径:先理解核心数据结构,再掌握数据读写,接着完成数据清洗和数据分析实战案例,最后补充常见问题和工程建议。文章中的代码均基于 Python 3 + Pandas 编写,读者可以直接复制运行。

2. Pandas 环境准备与安装

在开始写代码之前,先确认环境中已经安装了 Pandas。

2.1 检查 Python 版本

Pandas 对 Python 版本有一定要求。写教程时当前稳定版本通常支持 Python 3.9 及以上。如果你使用的是 Python 3.10,一般可以直接安装最新版 Pandas;如果使用更高版本或更老版本,建议先查看官方安装文档。

打开终端(Windows 为 CMD 或 PowerShell,macOS / Linux 为 Terminal),执行:

python --version

如果提示python不是内部或外部命令,可以尝试:

python3 --version

2.2 安装 Pandas

使用 pip 安装:

pip install pandas

如果你的环境同时存在多个 Python 版本,建议使用虚拟环境,避免包冲突。例如使用 venv:

python -m venv .venv .venv\Scripts\activate # Windows source .venv/bin/activate # macOS / Linux pip install pandas

安装完成后,验证版本:

import pandas as pd print(pd.__version__)

看到类似2.1.4的输出,说明安装成功。

2.3 搭配工具推荐

Pandas 只是一个库,还需要一个运行环境。常用选择:

  • Jupyter Notebook:适合交互式分析,数据展示直观。
  • PyCharm:适合写完整脚本和工程化分析代码。
  • VS Code + Python 插件:轻量、灵活。

本文示例在 Jupyter Notebook 和 PyCharm 中均可运行,关键是要把示例代码按顺序复制到同一个.py文件或 Notebook Cell 中。

3. 核心数据结构:Series 和 DataFrame

学习 Pandas,第一步不是背 API,而是弄清楚两个核心对象——Series和DataFrame。

3.1 Series:带索引的一维数组

Series可以理解为“带标签的一维数组”。它由两部分组成:

  • 数据部分:任意类型(整数、浮点数、字符串、对象)。
  • 索引部分:每个数据的标签,默认是0, 1, 2, ...。

创建一个最简单的 Series:

import pandas as pd s = pd.Series([10, 20, 30, 40]) print(s)

输出:

0 10 1 20 2 30 3 40 dtype: int64

你也可以显式指定索引:

s = pd.Series([10, 20, 30], index=['a', 'b', 'c']) print(s)

输出:

a 10 b 20 c 30 dtype: int64

这里的索引相当于“行名”,在数据分析中很有用,比如按月份、按城市作为索引。

3.2 DataFrame:带行列标签的二维表格

DataFrame是 Pandas 最常用的数据结构,可以理解成一张 Excel 表或一张数据库表。它由行索引(index)和列名(columns)组成。

创建一个 DataFrame:

import pandas as pd df = pd.DataFrame({ '姓名': ['张三', '李四', '王五'], '部门': ['技术部', '产品部', '运营部'], '薪资': [15000, 13000, 12000] }) print(df)

输出:

姓名 部门 薪资 0 张三 技术部 15000 1 李四 产品部 13000 2 王五 运营部 12000

创建后,可以查看一些常用属性:

print(df.shape) # 几行几列 print(df.columns) # 列名 print(df.index) # 行索引 print(df.dtypes) # 每一列的数据类型 print(df.info()) # 数据概览

df.info()的输出会显示行数、列数、非空值数量和每列类型,这对于检查数据完整性非常有用。

3.3 从列表、字典、NumPy 数组创建

除了字典方式,还可以从列表嵌套创建:

df2 = pd.DataFrame([ ['张三', '技术部', 15000], ['李四', '产品部', 13000] ], columns=['姓名', '部门', '薪资'])

从 NumPy 数组创建:

import numpy as np arr = np.array([[1, 2], [3, 4]]) df3 = pd.DataFrame(arr, columns=['A', 'B'])

理解这两个结构之后,就可以开始做“正事”了——读取数据。

4. 数据读取与写入:CSV、Excel、Parquet

数据分析的第一步通常是把外部数据载入到 Pandas 中。常用的数据源包括 CSV、Excel、Parquet、Feather 和数据库。

4.1 读取 CSV 文件

import pandas as pd df = pd.read_csv('sales_data.csv') print(df.head())

head()默认显示前 5 行,用于快速预览数据。如果 CSV 文件没有列名,可以指定header=None,并手动设置列名:

df = pd.read_csv('sales_data.csv', header=None, names=['日期', '销售额', '订单数'])

如果文件编码不是 UTF-8,会出现乱码。比如中文 CSV 经常使用gbk编码,可以这样读取:

df = pd.read_csv('sales_data.csv', encoding='gbk')

4.2 读取 Excel 文件

读取 Excel 需要额外的openpyxl或xlrd库,先安装:

pip install openpyxl

然后读取:

df = pd.read_excel('sales_data.xlsx', sheet_name='Sheet1')

如果 Excel 里有多个 Sheet,可以用sheet_name=None读取全部,返回一个字典,key 是 Sheet 名,value 是对应的 DataFrame。

4.3 读取 Parquet 和 Feather

在大数据场景下,Parquet 和 Feather 是两种高效的列式存储格式。很多从 Spark、Hive 同步过来的数据会直接落地为 Parquet,用 Pandas 读取非常方便。

df = pd.read_parquet('sales_data.parquet')

读取 Feather:

df = pd.read_feather('sales_data.feather')

需要提醒的是,read_parquet依赖pyarrow或fastparquet。安装命令:

pip install pyarrow

写回文件时,可以这样:

# 导出为 CSV df.to_csv('output_data.csv', index=False) # 导出为 Excel df.to_excel('output_data.xlsx', index=False) # 导出为 Parquet df.to_parquet('output_data.parquet') # 导出为 Feather df.to_feather('output_data.feather')

index=False的意思是不要把行索引导出为一列,通常更符合分析需求。

4.4 读取数据库表

如果数据在 MySQL 或 PostgreSQL 中,可以用read_sql:

import pandas as pd from sqlalchemy import create_engine engine = create_engine('mysql+pymysql://用户名:密码@localhost:3306/数据库名') df = pd.read_sql('SELECT * FROM sales_table', con=engine)

读取数据库前,务必确认权限和网络是否允许,生产环境不要随便用高权限账号执行操作。

5. 数据清洗实战:缺失值、重复值、类型转换

真实场景里的数据很少是干净的,数据清洗是 Pandas 学习中最耗时间的部分。下面结合一个业务示例演示。

先构造一份“员工销售数据”,故意加入缺失值和重复值:

import pandas as pd import numpy as np data = { '员工ID': ['E001', 'E002', 'E003', 'E004', 'E005', 'E001'], '姓名': ['张伟', '李娜', '王强', '赵敏', '刘洋', '张伟'], '部门': ['销售一部', '销售二部', '销售一部', np.nan, '销售三部', '销售一部'], '销售额': [12000, 9800, None, 15000, 8800, 12000], '日期': ['2024-01-05', '2024-01-06', '2024-01-07', '2024-01-08', '2024-01-09', '2024-01-05'] } df = pd.DataFrame(data) print(df)

输出:

员工ID 姓名 部门 销售额 日期 0 E001 张伟 销售一部 12000.0 2024-01-05 1 E002 李娜 销售二部 9800.0 2024-01-06 2 E003 王强 销售一部 NaN 2024-01-07 3 E004 赵敏 NaN 15000.0 2024-01-08 4 E005 刘洋 销售三部 8800.0 2024-01-09 5 E001 张伟 销售一部 12000.0 2024-01-05

可以看到,这份数据既有缺失值(NaN),又有完全重复的行(第 0 行和第 5 行),日期列也是字符串类型而不是时间类型。

5.1 检查缺失值

print(df.isnull()) print(df.isnull().sum())

isnull()会返回一个同形状的布尔 DataFrame,sum()按列统计缺失值数量。

5.2 处理缺失值

处理缺失值有两种思路:删除和填充。

删除包含缺失值的行:

df_drop = df.dropna() print(df_drop)

填充缺失值,比如销售额缺失,用该列均值填充:

df['销售额'] = df['销售额'].fillna(df['销售额'].mean())

部门缺失,用“未知部门”填充:

df['部门'] = df['部门'].fillna('未知部门')

注意:fillna返回的是新 DataFrame,不会原地修改,因此需要重新赋值,或者设置inplace=True。不过现在更推荐直接赋值的方式,可读性更好。

5.3 删除重复值

根据所有列判断重复行:

df = df.drop_duplicates()

如果只想根据“员工ID”判断重复,保留第一条:

df = df.drop_duplicates(subset=['员工ID'], keep='first')

热搜词里提到“如果指定两列的值均相同,则取第一条数据”,写法就是:

df = df.drop_duplicates(subset=['员工ID', '姓名'], keep='first')

keep='first'表示保留重复组中的第一条,keep='last'保留最后一条,keep=False删除所有重复行。

5.4 数据类型转换

Pandas 中常见的数据类型包括int64、float64、object、datetime64等。处理日期字符串时,需要转为时间类型:

df['日期'] = pd.to_datetime(df['日期']) print(df.dtypes)

把销售额从浮点型转成整数型:

df['销售额'] = df['销售额'].astype(int)

数据清洗后,再看一眼数据:

print(df)

输出:

员工ID 姓名 部门 销售额 日期 0 E001 张伟 销售一部 12000 2024-01-05 1 E002 李娜 销售二部 9800 2024-01-06 3 E004 赵敏 未知部门 15000 2024-01-08 4 E005 刘洋 销售三部 8800 2024-01-09

这样就得到一个相对干净、可继续分析的数据集。

6. 数据分析实战:筛选、排序、分组聚合

数据清洗完成后,就进入真正的分析阶段。这里用一个更完整的数据集,模拟“某公司销售订单明细”。

import pandas as pd sales_df = pd.DataFrame({ '订单号': ['A001', 'A002', 'A003', 'A004', 'A005', 'A006'], '地区': ['华东', '华北', '华东', '华南', '华北', '华南'], '品类': ['手机', '电脑', '手机', '平板', '手机', '电脑'], '销售额': [5000, 8000, 4500, 6000, 5200, 9200], '利润': [800, 1200, 600, 900, 700, 1500] }) print(sales_df)

6.1 按条件筛选数据

筛选销售额大于 5000 的记录:

high_sales = sales_df[sales_df['销售额'] > 5000] print(high_sales)

多条件筛选,用&表示“且”,用|表示“或”。注意每个条件都要加括号:

# 华东地区且销售额大于5000 result = sales_df[(sales_df['地区'] == '华东') & (sales_df['销售额'] > 5000)] print(result)

6.2 排序

按销售额降序排序:

sorted_df = sales_df.sort_values('销售额', ascending=False) print(sorted_df)

多列排序:

sorted_df = sales_df.sort_values(['地区', '销售额'], ascending=[True, False])

6.3 分组聚合

分组聚合是 Pandas 最核心的能力之一。比如统计每个地区销售额总和:

grouped = sales_df.groupby('地区')['销售额'].sum() print(grouped)

输出:

地区 华东 9500 华北 13200 华南 15200 Name: 销售额, dtype: int64

也可以一次统计多个指标:

result = sales_df.groupby('地区').agg({ '销售额': ['sum', 'mean', 'count'], '利润': 'sum' }) print(result)

这里的agg可以传入字典,key 是列名,value 是要执行的聚合函数。还可以用列表:

result = sales_df.groupby('地区')['销售额'].agg(['sum', 'mean', 'max', 'min'])

6.4 多列分组

按“地区 + 品类”两个维度统计:

result = sales_df.groupby(['地区', '品类'])['销售额'].sum().reset_index() print(result)

reset_index()的作用是把分组后的索引重新变成普通列,方便后续导出或继续处理。

6.5 透视表

透视表能更直观地展示二维汇总结果:

pivot_df = pd.pivot_table( sales_df, values='销售额', index='地区', columns='品类', aggfunc='sum', fill_value=0 ) print(pivot_df)

输出:

品类 平板 手机 电脑 地区 华东 0 9500 0 华北 0 5200 8000 华南 6000 0 9200

这就类似于 Excel 透视表,在分析报表中非常常见。

7. 数据可视化:用 Pandas + Matplotlib 快速出图

数据分析的最后一环往往是可视化。Pandas 本身不提供绘图能力,但可以很方便地调用 Matplotlib。

7.1 安装和导入

pip install matplotlib

在代码中启用 Matplotlib 并设置中文显示(避免中文乱码):

import matplotlib.pyplot as plt plt.rcParams['font.sans-serif'] = ['SimHei'] # Windows 常用黑体 plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题

macOS 或 Linux 可以换成['Arial Unicode MS']或系统支持的中文字体。

7.2 柱状图

按地区汇总销售额后画柱状图:

sales_by_region = sales_df.groupby('地区')['销售额'].sum() sales_by_region.plot(kind='bar', title='各地区销售额对比') plt.ylabel('销售额') plt.show()

7.3 折线图

如果有时间序列数据,折线图更适合:

time_df = pd.DataFrame({ '月份': ['2024-01', '2024-02', '2024-03', '2024-04'], '销售额': [2000, 3500, 2800, 4200] }) time_df.plot(x='月份', y='销售额', kind='line', marker='o', title='月度销售额趋势') plt.ylabel('销售额') plt.show()

7.4 饼图

展示品类占比:

sales_by_category = sales_df.groupby('品类')['销售额'].sum() sales_by_category.plot(kind='pie', autopct='%1.1f%%', title='品类销售额占比') plt.ylabel('') plt.show()

可视化的核心目的是让数据结论一目了然。实际项目中不需要花哨,清晰、准确更重要。

8. 常见问题与排查思路

8.1 常见报错速查表

下面列出新手使用 Pandas 时最常遇到的几类问题,以及排查思路。

问题现象常见原因解决思路
ModuleNotFoundError: No module named 'pandas'尚未安装,或装到了另一个 Python 环境确认当前解释器,执行pip install pandas
读取 CSV 中文乱码编码格式不对指定encoding='gbk'或encoding='utf-8'
列名有空格或中文,代码报错用df.列名访问有局限优先使用df['列名']
修改列后数据未生效忘记重新赋值Pandas 大多数操作返回新对象,需df = df.dropna()
KeyError: '列名'列名拼写错误或不存在用df.columns查看实际列名
groupby 后想转回普通表索引层级复杂使用.reset_index()
安装 pandas 报错,版本冲突Python 与 Pandas 版本不匹配查阅官方文档,升级 Python 或指定兼容版本

8.2 关于 Python 3.10 与 Pandas 的版本搭配

如果你的 Python 是 3.10,最新的 Pandas 稳定版一般都支持。比较稳妥的方式是:

pip install --upgrade pandas

如果安装后导入报错,比如缺少依赖库,可以先安装numpy、python-dateutil、pytz等基础依赖,再重装 Pandas。

8.3 处理大文件时内存不足

如果数据量很大,比如几个 GB 的 CSV,推荐分块读取:

chunk_iter = pd.read_csv('big_file.csv', chunksize=10000) result_parts = [] for chunk in chunk_iter: # 先做清洗 chunk = chunk.dropna() # 再做聚合 result_parts.append(chunk.groupby('类目')['销售额'].sum()) final_result = pd.concat(result_parts).groupby(level=0).sum()

分块读取的核心思路是:每次只处理 10000 行,减少内存占用,最后合并结果。

9. 最佳实践与工程建议

写了几年代码之后,你会发现 Pandas 入门不难,但要把代码写得稳定、可维护、可复用,还是需要一些工程经验的积累。下面分享几组实用建议。

9.1 用自定义函数组织数据处理流程

直接写一大段脚本,后期维护很痛苦。建议把每个环节封装成函数:

def load_data(file_path): return pd.read_csv(file_path) def clean_data(df): df = df.drop_duplicates(subset=['订单号']) df = df.dropna(subset=['销售额']) df['日期'] = pd.to_datetime(df['日期']) return df def analyze_data(df): return df.groupby('地区')['销售额'].sum().reset_index() def main(): df = load_data('sales.csv') df = clean_data(df) result = analyze_data(df) result.to_csv('sales_result.csv', index=False) if __name__ == '__main__': main()

这样每一步都可以单独测试,也方便复用。

9.2 尽量少用inplace=True

inplace=True会原地修改 DataFrame,虽然省内存,但在管道式处理和调试时容易产生副作用。推荐写法是“生成新对象并重新赋值”,逻辑更清晰,也便于链式操作。

9.3 注意链式赋值的坑

有些新手会这样写:

df[df['销售额'] > 5000]['标记'] = '高'

这被称为“链式赋值”,可能只修改了副本而不是原表,甚至会触发SettingWithCopyWarning。正确做法是:

df.loc[df['销售额'] > 5000, '标记'] = '高'

loc是先按条件定位,再修改列,稳定又明确。

9.4 数据备份与操作安全

涉及修改原始数据时,尤其是从数据库临时表或生产环境取数据,建议先做好备份:

df_backup = df.copy()

这样即使清洗逻辑写错了,也可以快速回退,不需要重新读一遍数据。

9.5 用nunique、value_counts辅助快速探查

数据分析前先摸清数据基本情况:

# 每个城市的数量分布 print(df['城市'].value_counts()) # 每个员工覆盖了多少个城市 print(df.groupby('员工')['城市'].nunique())

这些指令能帮你快速判断数据完整性和业务规则,比直接跑统计模型更有价值。

10. 实战扩展:金融风控场景中的 Pandas 应用

数据分析本身是方法,落地到具体领域才有生命力。这里以一个金融风控场景为例,演示 Pandas 的完整用法,也能帮你巩固前面所有内容。

假设有一份“用户交易记录”数据,字段包括:用户ID、交易金额、交易时间、是否命中风控规则。

import pandas as pd import numpy as np trade_data = pd.DataFrame({ '用户ID': ['U001', 'U002', 'U003', 'U001', 'U004', 'U002'], '交易金额': [2000, 8500, 300, 15000, 5000, None], '交易时间': ['2024-03-01 10:00:00', '2024-03-01 10:05:00', '2024-03-01 10:10:00', '2024-03-02 09:30:00', '2024-03-02 09:45:00', '2024-03-02 10:00:00'], '命中规则': ['否', '是', '否', '是', '否', '是'] })

第一步:清洗。把时间转为 datetime,删除空交易金额。

trade_data['交易时间'] = pd.to_datetime(trade_data['交易时间']) trade_data = trade_data.dropna(subset=['交易金额'])

第二步:按用户聚合。统计每个用户的交易次数、总金额、最大单笔金额、平均金额。

user_stats = trade_data.groupby('用户ID').agg({ '交易金额': ['count', 'sum', 'max', 'mean'] }).round(2) print(user_stats)

第三步:找出可疑用户。比如单日交易次数过多,或者命中风控规则的占比过高。这里简单演示“交易总金额大于 10000 的用户”:

user_total = trade_data.groupby('用户ID')['交易金额'].sum() high_risk_users = user_total[user_total > 10000] print(high_risk_users)

输出:

用户ID U001 17000.0 Name: 交易金额, dtype: float64

这个案例虽然简单,但完整覆盖了“读取、清洗、分组聚合、筛选”四条主线。金融风控场景中,还需要结合时间窗口分析、落库、监控预警等,这些都可以基于同样的 Pandas 功底逐步扩展。

11. 结束语:Pandas 这条路该怎么继续走

Pandas 是一座很好的桥,它能帮你从 Excel 表格思维过渡到编程化数据分析思维。通过本文,你应该已经掌握:

  • Series 和 DataFrame 两个核心数据结构;
  • CSV、Excel、Parquet、Feather 等文件的读写方式;
  • 缺失值、重复值、类型转换等数据清洗操作;
  • 筛选、排序、分组聚合、透视表等分析手段;
  • 配合 Matplotlib 输出可视化图表的基本流程;
  • 常见报错的排查思路和工程化的写法建议。

下一步,建议按这个顺序继续深入:先自己找一份真实数据集,完整跑一遍清洗和分析流程;然后学习apply自定义函数,解决更复杂的业务逻辑;接着了解merge和concat,掌握多张表关联;最后可以接触 Spark 或 Dask,让 Pandas 分析能力延伸到更大的数据规模。

如果本文对你有帮助,可以收藏备用;遇到具体问题,欢迎在评论区留言交流。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询