用Python实现数据整理与图表生成:pandas+matplotlib实战
9.5.1 数据整理与图表生成案例这个标题看起来是教材或课程里的一节但落到实际工作里它对应的是每个做数据处理的人每天都要面对的那条链路拿到一份乱糟糟的原始数据先清洗、再规整最后画成图表让别人能一眼看懂。这篇文章不绕弯子直接用 Python 生态里最常用的 pandas matplotlib 组合把这套流程完整走一遍。你不需要懂什么高深算法只要装了 Python能跑脚本就能照着做。案例的核心就三件事第一把 Excel 或 CSV 里的脏数据读进来并整理成结构化表格第二用 pandas 做分组、聚合和透视第三用 matplotlib 生成折线图、柱状图和饼图并支持批量导出。整个过程适合数据分析入门者、运营岗位需要做周报月报的同学以及想把重复性图表工作脚本化的工程师。下面会给出可复制的代码、每一步的预期输出、常见报错和排查方法。1. 核心能力速览能力项说明项目类型数据整理与图表生成案例Python 脚本化实现核心依赖pandas、matplotlib、openpyxl、Jupyter Notebook 可选主要功能数据读取、缺失值处理、类型转换、分组聚合、透视表、折线图、柱状图、饼图、批量导出运行平台Windows / macOS / Linux 均可硬件要求普通办公电脑即可无 GPU 需求启动方式命令行运行 Python 脚本或 Jupyter Notebook 分步执行是否支持 API本身不提供 HTTP 接口但可封装为函数或命令行工具是否支持批量任务支持可通过循环批量处理多个文件并分别导出图表适合场景周报月报、销售数据分析、课程作业、运营报表、快速数据可视化输出格式PNG / JPG / SVG 图片Excel 整理结果从能力上看这是一个典型的轻量级数据处理方案不涉及模型部署、不依赖显卡重点在于把重复劳动脚本化。如果数据量在百万行以内pandas 完全够用超过这个量级再考虑 Dask 或 Spark不在本文讨论范围。2. 适用场景与使用边界先说要解决什么问题。数据整理解决的是数据不干净、结构不统一的问题表头有合并单元格、日期格式五花八门、数值列里混着文本、有空行空列、有重复记录。图表生成解决的是数据看不出趋势的问题同一份数据用表格看和用折线图看结论完全不同。适合用这套方案的人有三类报表工程师和小团队运营每周固定从后台导出 CSV做清洗后出图脚本跑一次能省半小时。数据分析初学者用真实数据练手理解 pandas 的 groupby、merge、pivot_table 这些核心操作。需要快速验证数据的工程师不想打开 Excel 手动操作直接用代码完成从数据到图表的全流程。不适合什么场景也要说清楚数据量超过千万行、需要分布式计算时pandas 单机内存会吃紧。需要交互式图表缩放、筛选、联动时建议改用 Plotly 或 ECharts。图表需要嵌入 Web 系统展示时不建议直接输出 PNG优先考虑前端图表库。原始数据涉及用户隐私、企业经营敏感信息时注意脱敏和授权不要将未处理的原始文件随意分享。合规方面处理他人数据时需确认数据来源合法尤其是涉及个人信息的 Excel 文件汇总后发布前要检查是否存在手机号、身份证号等敏感字段泄漏。这一步不是形式是底线。3. 环境准备与前置条件这套流程对硬件几乎没有要求重点在软件环境。3.1 操作系统与 Python 版本Windows 10/11、macOS、主流 Linux 发行版都可以。Python 建议 3.9 及以上版本pandas 和 matplotlib 对 Python 3.8 以下版本的支持已经逐步停止。检查 Python 版本python --version如果没有装 Python去官网下载安装包安装时勾选 Add Python to PATH。如果不想破坏系统环境建议先装 Miniconda 或 venv 虚拟环境再创建独立的实验环境。3.2 依赖库安装需要安装的库就四个其中 numpy 会被 pandas 自动依赖装上pip install pandas matplotlib openpyxl numpypandas负责数据读取、清洗、分组、聚合。matplotlib负责绘图。openpyxl负责读写 Excel 文件。只处理 CSV 可以不装但现实场景里 Excel 文件更常见。numpypandas 的底层计算库一般随 pandas 自动安装。如果下载速度慢使用国内镜像源pip install pandas matplotlib openpyxl -i https://pypi.tuna.tsinghua.edu.cn/simple3.3 数据准备本文演示用的数据是一份模拟的销售订单表包含以下字段字段名说明示例order_id订单编号A1001date下单日期2025-01-05region地区华东category商品类别手机sales销售额3999quantity数量2实际使用时把文件路径替换成你自己的数据路径即可。建议在项目目录下建好三个文件夹data存放原始数据output存放整理后的结果charts存放生成的图片。目录结构清晰后面做批量任务会省很多事。4. 数据整理pandas 实操分步讲解这一节是整篇文章的核心。数据整理不是一句读进来就行而是要处理真实数据里的各种脏问题。下面的步骤都基于一份模拟数据但每一步都对应真实场景。4.1 读取数据并查看结构先把 Excel 读进来观察数据长什么样import pandas as pd # 读取 Excel 文件 df pd.read_excel(data/sales_raw.xlsx, sheet_name订单明细) # 查看前 5 行 print(df.head()) # 查看整体信息列名、非空数量、数据类型 print(df.info()) # 查看数值列的统计描述 print(df.describe())预期输出中df.info()会展示每一列的名称、非空数量和数据类型。这里要重点检查两个地方一是数值列是否被读成了 object 类型比如销售额里混入了待确认这类文本二是日期列有没有变成字符串。如果发现列名不规范比如带空格、带中文括号可以用 rename 统一处理df df.rename(columns{ 销售 额: sales, 下单日期文本: date })4.2 缺失值与重复值处理缺失值处理要分情况数值列可以填充 0 或平均值文本列可以填充未知也可以直接删除缺失比例过高的行。下面给出一套组合处理逻辑# 查看每列缺失值数量 print(df.isnull().sum()) # 数值列填充 0 df[sales] df[sales].fillna(0) # 关键字段缺失的行直接删除 df df.dropna(subset[order_id, date]) # 删除完全重复的行 df df.drop_duplicates() # 按 order_id 去重保留第一条 df df.drop_duplicates(subset[order_id], keepfirst)判断标准处理后所有关键字段无空值且每个订单编号唯一。如果出现大量订单重复说明上游导出逻辑有问题需要提醒数据提供方。4.3 数据类型与日期标准化日期列是重灾区。常见问题包括2025/1/5202501052025-01-05 00:00:00混在一起。用to_datetime统一转换df[date] pd.to_datetime(df[date], errorscoerce) # 转换后仍有空值说明原始格式无法解析先打印出来排查 print(df[df[date].isnull()])数值列如果混入了文本用pd.to_numeric配合 coerce 参数强制转换无法转换的变为 NaN 再处理df[sales] pd.to_numeric(df[sales], errorscoerce) df[sales] df[sales].fillna(0)4.4 新增列与数据提炼从日期列中提取月份、季度从其他字段组合出新列这是整理数据最常用的操作df[month] df[date].dt.to_period(M) df[quarter] df[date].dt.quarter df[avg_price] df[sales] / df[quantity]新增列后数据就具备了多维度聚合的基础。4.5 分组聚合与透视表这一步解决按地区看总销售额这类问题。先用 groupby 实现# 按地区统计销售额和订单数 region_summary df.groupby(region).agg( 总销售额(sales, sum), 订单数(order_id, nunique), 平均客单价(sales, mean) ).reset_index() print(region_summary)再用 pivot_table 做地区与商品类别的交叉统计pivot pd.pivot_table( df, valuessales, indexregion, columnscategory, aggfuncsum, fill_value0 ) print(pivot)透视表出来后数据整理阶段就完成了。此时可以把整理后的数据导出成 Excel方便后续核对df.to_excel(output/sales_clean.xlsx, indexFalse)5. 图表生成matplotlib 实操分步讲解数据整理干净了画图才有意义。这一节直接用上一节的结果生成三种常见图表。5.1 中文字体设置matplotlib 默认字体不支持中文直接绘图会显示方框。这一步放在最前面import matplotlib.pyplot as plt # 设置中文字体Windows 推荐 SimHeimacOS 推荐 PingFang SC plt.rcParams[font.sans-serif] [SimHei, PingFang SC, Microsoft YaHei] plt.rcParams[axes.unicode_minus] False # 解决负号显示问题如果系统里没有这些字体需要先安装字体或在系统中查看可用字体列表。5.2 柱状图各地区销售额对比柱子图适合对比分类数据的数值大小fig, ax plt.subplots(figsize(10, 6)) ax.bar(region_summary[region], region_summary[总销售额], color#4C72B0) # 在柱子上方标出数值 for i, v in enumerate(region_summary[总销售额]): ax.text(i, v, f{v:,.0f}, hacenter, vabottom, fontsize10) ax.set_title(各地区销售总额对比, fontsize14) ax.set_xlabel(地区) ax.set_ylabel(销售额元) ax.grid(axisy, linestyle--, alpha0.5) plt.tight_layout() plt.savefig(charts/region_sales_bar.png, dpi150) plt.show()5.3 折线图月度销售趋势折线图适合看时间趋势# 先按月份聚合销售额 monthly_sales df.groupby(month)[sales].sum().reset_index() monthly_sales[month] monthly_sales[month].astype(str) fig, ax plt.subplots(figsize(12, 6)) ax.plot(monthly_sales[month], monthly_sales[sales], markero, linewidth2) ax.set_title(月度销售趋势, fontsize14) ax.set_xlabel(月份) ax.set_ylabel(销售额元) ax.grid(linestyle--, alpha0.5) plt.tight_layout() plt.savefig(charts/monthly_trend_line.png, dpi150) plt.show()这里注意一个细节month 列是 Period 类型需要先转成字符串再传给 matplotlib否则坐标轴的刻度标签会显示异常。5.4 饼图销售份额占比饼图适合展示占比但是类别过多时慎用超过 6 类建议改成横向条形图category_summary df.groupby(category)[sales].sum().sort_values(ascendingFalse) top_categories category_summary.head(6) fig, ax plt.subplots(figsize(8, 8)) ax.pie( top_categories, labelstop_categories.index, autopct%.1f%%, startangle90, counterclockFalse ) ax.set_title(各品类销售占比, fontsize14) plt.tight_layout() plt.savefig(charts/category_share_pie.png, dpi150) plt.show()判断图表是否成功的标准很简单图片能正常保存到指定目录、中文不显示方框、坐标轴刻度没有重叠、数值标注清晰可读。6. 图表自动导出与批量任务单个文件画三张图只是入门真实场景往往是每月要出 30 张图或按城市分别出图。这时候把代码封装成函数配合循环就能批量处理。6.1 封装成函数先定义一个通用的绘图函数输入是分组后的 DataFrame输出是图片文件def plot_region_bar(data, output_path): fig, ax plt.subplots(figsize(10, 6)) ax.bar(data[region], data[总销售额], color#4C72B0) for i, v in enumerate(data[总销售额]): ax.text(i, v, f{v:,.0f}, hacenter, vabottom, fontsize10) ax.set_title(各地区销售总额对比) ax.set_xlabel(地区) ax.set_ylabel(销售额元) ax.grid(axisy, linestyle--, alpha0.5) plt.tight_layout() plt.savefig(output_path, dpi150) plt.close(fig) # 关闭画布释放内存注意最后一行plt.close(fig)批量循环时如果不关闭画布内存会持续增长重复几百次后脚本可能卡死。6.2 按分组字段批量生成假设要按月份批量生成各地区的销售图表可以先分组再对每个分组单独调用绘图逻辑import os os.makedirs(charts/by_month, exist_okTrue) for month_val, group in df.groupby(month): # 对该月数据按地区聚合 g group.groupby(region)[sales].sum().reset_index() file_name fcharts/by_month/{month_val}.png plot_region_bar(g, file_name) print(f已生成: {file_name})这个模式的扩展性很好按城市拆分把 groupby 的列换成city。按商品类别拆分换成category。批量处理多个 Excel 文件外层再套一个文件遍历循环。6.3 批量读取多个数据文件如果数据分散在多个 Excel 里用glob配合 pandas 统一读取import glob all_files glob.glob(data/*.xlsx) df_list [] for file in all_files: tmp pd.read_excel(file) df_list.append(tmp) df_all pd.concat(df_list, ignore_indexTrue) print(df_all.shape)这里的关键是把读取数据和计算逻辑分离文件再多也只是多跑几次循环。需要注意的是多个文件的列名必须一致否则 concat 时会按列名对齐导致数据错乱。建议在批量读取前统一打印每个文件的列名做检查。7. 资源占用与性能观察这套方案不需要 GPU资源占用主要看内存和 CPU重点观察三个场景。7.1 数据量对内存的影响pandas 读数据时会一次性加载进内存。以一份 100 万行、20 列、含文本和数值的 Excel 为例导入后内存占用可能达到几百 MB 到 1 GB 级别。如果电脑内存只有 8GB同时打开浏览器和其他软件后再跑 pandas 会明显变卡。降低内存的方法读取时指定只用到的列pd.read_excel(file, usecols[order_id, date, sales])。用dtype参数指定列类型比如小数列的float32。不要频繁复制 DataFrame尽量在原对象上操作。7.2 绘图对资源的消耗matplotlib 单个图表的内存开销不大但在循环里保存几百张图时必须用plt.close(fig)释放画布资源。另外dpi 设置越高保存的图片文件越大绘制时间越长。日常报表 dpi150 够用需要印刷才设置 dpi300。7.3 性能观察方法在 Windows 任务管理器或 macOS 活动监视器里观察 Python 进程的 CPU 和内存占用即可。更精确的方法是在脚本里打印运行时长import time start time.time() # 中间放数据处理和绘图代码 print(f运行耗时: {time.time() - start:.2f} 秒)通过这段代码可以量化验证数据读取占多长时间、绘图占多长时间、瓶颈在哪个环节。如果发现读取很慢优先检查是不是把不必要的列也读进来了。8. 常见问题与排查方法把这套流程跑下来最常见的几个问题都集中在环境、编码和路径上。整理成排查表格问题现象可能原因排查方式解决方案ModuleNotFoundError: No module named pandas依赖未安装或安装了多个 Python 环境执行pip list查看是否安装pip install pandas并确认 pip 与 python 属于同一环境中文显示为方框matplotlib 字体设置缺失检查plt.rcParams[font.sans-serif]是否设置设置中文字体或安装中文字体后重启脚本读取 Excel 时报错EngineErroropenpyxl 未安装查看完整报错信息pip install openpyxl日期解析后全是 NaT原始日期格式多样打印原始值前 10 条用errorscoerce定位问题再手动指定格式柱状图坐标轴标签重叠分类太多或标签太长观察图片中标签是否重叠用plt.xticks(rotation45)旋转标签或改用横向柱状图批量循环内存增长未关闭画布观察任务管理器内存变化每次循环结束后调用plt.close(fig)保存图片时路径不存在输出目录未创建检查报错中的路径用os.makedirs先创建目录导出 Excel 后中文乱码Excel 列内容与编码设置问题检查文件在 Excel 中具体表现导出时用df.to_excel不需要额外编码参数如果写 CSV 则指定encodingutf-8-sigValueError: Buffer dtype mismatchnumpy 与 pandas 版本不兼容执行pip list查看版本升级对齐版本pip install --upgrade pandas numpy另外补充一个隐蔽问题做 groupby 后再画图如果分类字段是数值型比如城市编码被读成了 int画图时 X 轴刻度会变成一堆数字。判断方法是在聚合前打印df.dtypes确认分组列类型必要时先转成字符串。9. 最佳实践与使用建议这套数据整理与图表生成流程跑通只是第一步能稳定、可复用才是目标。下面几条建议来自实际项目中的高频经验。第一把流程拆成独立脚本。不要把所有代码写在一个文件里。建议至少拆分三个脚本load_data.py负责读取和清洗aggregate.py负责计算指标plot_charts.py负责绘图输出。这样数据源变化时只需要改第一个脚本指标口径变化时只改第二个不会牵连绘图逻辑。第二口径要固化。销售总额按什么时间维度算、退款订单是否包含、单位是元还是万元这些口径必须在脚本里明确定义并在输出文件名或表格说明中标出。否则同一个数字不同人算出不同结果图表越精致越没人信。第三输出目录和命名规范。图片文件名建议包含指标维度和时间范围例如charts/2025Q1_region_sales.png比chart1.png好得多。多次运行会覆盖旧文件如果需要保留历史版本在文件名里加上生成日期。第四批量任务必须加日志。每处理一个文件就打印一行已处理: 文件名处理失败时打印异常并继续跑下一个。不要用裸的 try-except 吞掉异常至少要把错误信息写入日志文件。第五涉及隐私和版权数据时先脱敏。如果原始 Excel 里有手机号、身份证号、详细地址在写进报告或公开分享前必须打码或删除对应列。就算只是内部使用也要限制文件的访问权限不要直接放在共享盘或者公开的网盘目录里。第六先小样本验证再全量跑。在完整数据上跑之前先用df.sample(1000)抽一小部分数据验证代码逻辑和数据口径确认无误后再处理全量数据。这一步能避免代码跑完、发现口径错了、全部重来的尴尬。10. 总结与下一步这个数据整理与图表生成案例最值得尝试的点是它把读数据、清数据、算指标、出图完整串成了一条可复用的脚本链路。相比手动用 Excel 操作代码方案有两点不可替代的优势一是过程可复现任何人用同一份代码和数据都能得到相同结果二是可批量换个目录、换个分组字段就能处理新数据不需要重新做一遍手工操作。建议你先跑通文中的三张基础图表然后把自己手里最常做的一份周报或月报数据套进去。最先要验证的是日期解析和分组聚合两个环节这两处最容易出问题。最容易踩的坑已经写在排查表格里中文乱码、字体显示、Excel 读取报错遇到问题优先检查版本和环境。下一步的扩展方向如果对交互式图表有需求可以在 matplotlib 的基础上学习 Plotly同样的 DataFrame 数据可以直接转成网页图表。如果数据量变大可以研究 pandas 的 chunked 读取方式或者把处理完的数据写入 SQLite 数据库再查。如果想让这套流程更自动化可以用schedule库定时执行脚本把生成的图表自动发到邮箱或企业微信。这篇文章的核心代码可以直接复制调整使用。建议收藏备用实际做数据报表时把它当成一套基础模板在它上面按自己的业务字段做修改比从零开始写要快得多。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →