从数据清洗到可视化:Pandas数据分析避坑指南与完整实操

发布时间:2026/9/28 11:04:14
从数据清洗到可视化:Pandas数据分析避坑指南与完整实操 用Pandas做数据分析这几年我最大的感受是绝大多数人不是不会Pandas而是被“脏数据”卡在了门口。数据清洗这一步要花掉整个项目至少一半的时间但网上教程往往只讲函数用法不讲为什么这么做、踩过哪些坑。这篇文章我就围绕“从数据清洗到可视化”这条完整链路把实际操作中反复用到的核心方法、判断逻辑和避坑经验一次讲清楚。不管你是刚接触数据分析的初学者还是已经在用Pandas处理日常报表的从业者这篇文章都能给你一套可以照着抄的实操方案。我会用一个虚拟的电商订单数据从导入到出图的完整过程把缺失值处理、数据类型转换、文本清洗、分组聚合到可视化一整套流程串起来。你不需要额外准备数据集跟着文章里的代码自己造一份也能跑通。1. 先想清楚数据分析为什么一定要走完“清洗到可视化”这条链路很多新手拿到一张Excel表就直接画图结果图是出来了但图里的结论是错的。根本原因是原始数据几乎不可能直接满足分析需求空值、重复值、类型错乱、文本带杂质这四类问题是每份真实数据里都会出现的。1.1 数据分析的常见误区直接拿原始数据画图我见过不少同学把数据读进来plt.show() 一画看到曲线有波动就开始写结论。实际上如果销售金额字段里有几十个空值聚合出来的月销售额就是偏低的如果订单号有重复每天的订单量就是虚高的。这些错误不会让程序报错但会让结论失真而且越往后越难排查。数据分析的正确顺序应该固定成一条流水线读取数据、快速体检、清洗加工、分析计算、可视化输出。清洗不是可有可无的步骤它是整条链路的地基。地基不牢后面画图再漂亮也是空中楼阁。1.2 Pandas在整条链路中的核心定位Pandas覆盖的是“数据加工厂”这一段从读取原始数据开始到产出干净的分析表为止。它把Excel里需要手动点的操作——删除空行、分列、去重、替换——全部变成了可复现的代码。这点在工作里尤其重要因为你上个月跑的清洗逻辑这个月来了新数据还要再跑一遍。用代码清洗意味着你的处理过程是可追溯、可重跑的而不是每次都在Excel里手工操作。可视化本身虽然有Matplotlib、Seaborn这些库来完成但它们消费的数据必须是Pandas处理好的DataFrame。所以说Pandas是整个分析流程的心脏清洗是给心脏供血的血脉可视化则是把分析结果展示给外界的手和嘴。2. 准备阶段读取数据并做快速体检拿到一个数据集别急着清洗先把数据“摸一遍”。我习惯的操作顺序是读取 → 看形状 → 看字段类型 → 看统计描述 → 看缺失值分布。这套流程5分钟能完成但能帮你建立对数据的基本认知。2.1 读取Excel与CSV时的编码和路径细节读取CSV最经典的坑是编码问题。中文数据最常见的编码是UTF-8和GBKPandas默认用UTF-8解码遇到GBK文件就会报 UnicodeDecodeError。解决方案很简单import pandas as pd df pd.read_csv(订单数据.csv, encodinggbk) # 或者用 utf-8 df pd.read_csv(订单数据.csv, encodingutf-8)如果两种编码都试了还是报错可以试试encodinggb18030它是GBK的超集兼容性更好这是我处理国内导出数据时最常用的兜底编码。另外要注意文件路径尽量不要带中文某些环境对中文路径支持不友好会莫名其妙报找不到文件。读取Excel用pd.read_excel(订单数据.xlsx, sheet_name销售明细)如果Excel里有多个Sheet需要明确指定读取哪张表。还有个常用参数skiprows当表格前几行是标题说明时直接跳过去不用手工删。2.2 用info、describe和isnull完成数据概览读进来数据后我用三行代码完成初步体检df.info() # 字段名、非空数量、数据类型 df.describe() # 数值列的统计描述 df.isnull().sum() # 每列缺失值数量info()最核心的信息有三个总行数、每列的非空数量、每列的数据类型。如果某个列应该是数值但显示 object说明里面有文本杂质这列就要重点清洗。isnull().sum()则直接告诉我哪些列有缺失、缺多少决定后面是用删除还是用填充。这一步千万不要跳过。数据体检就像看病先量体温你连基础指标都不看就直接开药大概率会开错。3. 数据清洗真正拉开分析师差距的环节清洗的每一类问题都有对应策略但策略的选择取决于业务场景。我下面拆开讲每一类都附上判断逻辑和代码。3.1 缺失值处理删除还是填充需要先问业务缺失值处理没有万能公式核心思路是先分清缺失产生的场景。随机缺失可以放心处理而系统性缺失往往意味着业务逻辑有问题。如果某列缺失比例极低比如5%以下而且该列不是分析的关键指标直接删除这些行即可df_clean df.dropna(subset[订单金额])如果缺失的是数值型指标且数据分布比较平稳可以用均值或中位数填充。我更推荐中位数因为它不受极端值影响比如员工薪资这个字段如果有几个高管的高薪数据均值会被拉高但中位数很稳df[订单金额] df[订单金额].fillna(df[订单金额].median())如果缺失的是时间序列数据可以用前后填充法比如用前一天的数值补今天的空缺df[销量].fillna(methodffill)就是一个很实用的操作。填充完之后要验证一下df.isnull().sum()应该全部为0。很多新手填充完不检查后面画图时又报错回头查半天才发现是漏了几个空值。3.2 重复值与异常值这两类脏数据会直接扭曲分析结论重复值处理相对简单用drop_duplicates()即可。但填参数时要注意如果只按订单号去重可能把同一个订单下的不同商品行误删所以通常要指定子集df df.drop_duplicates(subset[订单号, 商品名称], keepfirst)异常值处理要先“找”再“处理”不能凭感觉删。我常用两种方法数值型字段用 IQR四分位距识别离群点任何小于 Q1-1.5×IQR 或大于 Q31.5×IQR 的值都算异常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 df[(df[订单金额] lower_bound) (df[订单金额] upper_bound)]但异常值不一定要删。比如订单金额特别大的企业团购单如果业务上合法存在删掉反而丢失了重要信息。我的习惯是先筛选出异常值单独看一下如果是录入错误比如多打了个0就修正如果真实存在就保留。所谓清洗不是把数据洗到“最干净”而是洗到“符合业务事实”。3.3 数据类型转换与文本清洗正则表达式在这里派上大用场数据类型的坑在中文业务数据里尤其常见。金额字段“1,234.56”是字符串日期字段“2024/05/11”是字符串还有“销量12件”这种带单位的文本。处理思路是先把杂质去掉再转成目标类型。最常见的金额清洗场景字符串里有千分位逗号和货币符号df[订单金额] ( df[订单金额] .astype(str) # 强制转成字符串 .str.replace(,, , regexFalse) # 去掉逗号 .str.replace(¥, , regexFalse) # 去掉货币符号 .astype(float) # 转成浮点数 )日期字段用pd.to_datetime()统一转换df[订单日期] pd.to_datetime(df[订单日期])这里有个很实用的小细节to_datetime支持多种格式的日期字符串比如“2024/05/11”“2024-05-11”“20240511”它会自动识别不用提前格式化。但如果遇到无法解析的格式会报错或变成 NaT这时候可以用errorscoerce参数把解析失败的值转成空值再做缺失处理。正则表达式在文本清洗中威力巨大。比如从“张三-北京-13800138000”这样的备注字段里提取手机号import re df[手机号] df[备注].str.extract(r(1[3-9]\d{9}))str.extract()配合正则分组可以把匹配的内容直接取出来。再比如清洗商品名称里的空格和特殊符号df[商品名称] df[商品名称].str.replace(r\s, , regexTrue)3.4 数据变换重塑、分组和特征工程的基础操作清洗完之后数据已经“干净”了但要想分析得顺手常常还需要做变换。最常用的是这些筛选特定行和列用loc做条件选择df_high df.loc[df[订单金额] 500, [订单号, 订单金额]]新增计算列比如订单金额减去成本得到利润df[利润] df[订单金额] - df[成本]排序后取Top Ndf_top10 df.nlargest(10, 订单金额)这里有一个非常重要的操作习惯问题在做清洗和变换的时候Pandas很多方法默认不修改原DataFrame而是返回一个新的DataFrame。新手经常忘记赋值导致操作完发现原表没变。比如df.drop_duplicates()不写赋值的话去重结果就丢了。我的经验是养成“每次操作都必须赋值给新变量或者原变量”的习惯而不是指望方法内部自动修改。inplaceTrue这个参数我建议能不用就不用。它在部分版本里会触发链式赋值的坑而且一旦用了就无法回退。用df df.drop_duplicates()这种写法既清晰又能保留一个可回退的操作路径。4. 数据分析让清洗后的数据产生业务价值数据干净了接下来进入分析阶段。Pandas在这个环节的核心能力是分组聚合、合并连接和时间序列处理。4.1 分组聚合groupby的正确打开方式groupby是Pandas里最高频的分析工具思路和Excel的数据透视表完全一致。按商品类别汇总销售额和订单量result ( df.groupby(商品类别) .agg( 总销售额(订单金额, sum), 平均客单价(订单金额, mean), 订单量(订单号, count) ) .reset_index() )agg里可以用字典或元组形式对不同的列指定不同的聚合函数这个写法比groupby().sum()灵活得多。聚合之后reset_index()是个好习惯它能把分组索引转成普通列方便后续继续处理或者可视化。如果你需要按多个维度看数据比如“每个城市每月的销售额”把多个列名传给groupby就行monthly_city ( df.groupby([城市, df[订单日期].dt.to_period(M)]) .agg(总销售额(订单金额, sum)) .reset_index() )这里的to_period(M)能把日期降维到月份非常配合时序分析。4.2 相关性分析与业务洞察当你有多个数值型字段时可以用corr()快速看它们的相关性corr df[[订单金额, 成本, 利润, 客户评分]].corr()结果是一个相关系数矩阵值越接近1说明正相关越强越接近-1说明负相关越强。比如发现“客户评分”和“利润”相关性很高那业务上可以尝试提升服务质量来拉动利润这就为后续的商业决策提供了数据依据。相关性分析有个要注意的点数据量太小时相关系数没有统计意义至少几百条样本才比较可靠。另外相关系数只能反映线性关系非线性关系它测不出来所以也别完全依赖这个数字。4.3 时间序列数据的进阶处理时间序列分析里最常用的是重采样和窗口计算。重采样就是把时间频率从低到高或从高到低转换比如把日数据汇总成月度df.set_index(订单日期, inplaceTrue) monthly_sales df[订单金额].resample(M).sum()滚动窗口则用来平滑波动、观察趋势比如算最近7天的平均销量df[销量_7日均值] df[销量].rolling(window7).mean()滚动均值的窗口大小需要根据业务周期决定。电商数据用7天平滑周度波动金融数据常用20日或60日平滑更长的周期。窗口太小平滑效果差窗口太大又会把真实的拐点抹掉多试几个窗口值找平衡点就好。另有一个被问得很多的参数是ewm指数加权移动平均。它和rolling的区别在于rolling对窗口内数据等权平均ewm对越近的数据权重越高。在数据有明显趋势延续的场景比如销量预测ewm通常比简单滑动平均反应更快df[销量_ewm] df[销量].ewm(alpha0.3).mean()这里的alpha是衰减因子值越大就越关注近期数据。0.3意味着近期数据的权重衰减得比较快适合对变化敏感的业务。5. 可视化做好图之前先做好表很多人一上来就想画漂亮的图实际上图的背后是“组织好的数据”。先做表再做图顺序不能乱。5.1 Matplotlib与Seaborn的基础设置可视化我习惯用 Matplotlib Seaborn 组合。Matplotlib 负责底层绘图Seaborn 封装了更美观的默认样式和更方便的统计图。先做初始化设置import matplotlib.pyplot as plt import seaborn as sns plt.rcParams[font.sans-serif] [SimHei] # 显示中文 plt.rcParams[axes.unicode_minus] False # 解决负号显示成方块 sns.set_style(whitegrid)中文字体的问题是国内用户的必修课。不设置中文字体图表里所有中文都会变成方框。SimHei在Windows上基本可用如果是Mac环境可以用Arial Unicode MS或者安装思源黑体后指定字体名。5.2 四类高频图表及其适用场景柱状图适合展示分类对比比如各品类销售额plt.figure(figsize(10, 6)) sns.barplot(dataresult, x商品类别, y总销售额) plt.title(各品类销售额对比) plt.xticks(rotation45) plt.tight_layout() plt.show()折线图适合展示时间趋势比如月度销售曲线。用前文的monthly_sales结果直接画即可。折线图的横轴如果是时间Pandas会自动处理刻度如果刻度太密可以手动设置每隔几个月显示一个标签。箱线图适合发现分布异常比如各品类的价格离散程度plt.figure(figsize(10, 6)) sns.boxplot(datadf, x商品类别, y订单金额) plt.show()箱线图能直观看出每个品类的中位数、四分位距和离群点是数据清洗阶段发现问题的一大利器。热力图适合呈现相关性矩阵plt.figure(figsize(8, 6)) sns.heatmap(corr, annotTrue, cmapcoolwarm, center0) plt.show()annotTrue会在格子里显示数值cmap控制颜色映射。这张图一眼就能看出哪些指标高度相关对做特征筛选帮助很大。5.3 从静态图表到可视化大屏的延展Matplotlib 画出的静态图适合分析和汇报。但如果要做数据看板把多张图表组合到一个页面里可以用subplot或者GridSpec把多张图拼接到一起。更专业的方案是使用支持交互的库比如 Plotly 或 Pyecharts这两者生成的图表可以缩放、悬停查看数据导出成HTML后在浏览器里展示效果接近真正的可视化大屏。不过我的建议是先用Pandas把清洗和聚合做好把数据导出成干净的CSV再交给ECharts或者大屏工具去消费。Pandas不是做炫酷大屏的工具而是保证大屏数据准确的地基。你先有了正确的数据再去谈好看顺序不要颠倒。6. 完整实操从一份脏乱的订单表到可视化结论下面我用一个实际的虚拟数据来串联前面所有方法。假设你拿到一份电商订单Excel包含1000行记录字段有订单号、订单日期、商品类别、商品名称、订单金额、成本、客户城市。6.1 原始数据的问题清单这份数据模拟了真实项目里的典型脏乱差订单金额列有的带千分位逗号有的缺失有的异常大订单日期有“2024/05/11”“20240511”“2024-5-11”三种格式商品名称里有空格和特殊符号还有若干完全重复的行。用df.info()查看订单金额显示为object类型日期也是object类型。这种数据如果直接画图结果会非常离谱金额是字符串无法求和日期无法排序重复行会让柱状图虚高。每个问题都必须走一遍前面说的清洗流程。6.2 清洗与分析完整代码import pandas as pd import matplotlib.pyplot as plt import seaborn as sns # 1. 读取数据 df pd.read_excel(订单数据.xlsx, sheet_name销售明细) # 2. 快速体检 print(df.info()) print(df.isnull().sum()) # 3. 去重 df df.drop_duplicates(subset[订单号, 商品名称], keepfirst) # 4. 清洗金额字段并转数值 df[订单金额] ( df[订单金额].astype(str) .str.replace(,, , regexFalse) .str.replace(¥, , regexFalse) .astype(float) ) # 5. 缺失金额使用中位数填充 df[订单金额] df[订单金额].fillna(df[订单金额].median()) # 6. 统一日期格式 df[订单日期] pd.to_datetime(df[订单日期], errorscoerce) df df.dropna(subset[订单日期]) # 7. 清洗商品名称 df[商品名称] df[商品名称].str.replace(r\s, , regexTrue) # 8. 新增利润列 df[利润] df[订单金额] - df[成本] # 9. 月度销售额聚合 df[月份] df[订单日期].dt.to_period(M) monthly df.groupby(月份).agg(月销售额(订单金额, sum)).reset_index() monthly[月份] monthly[月份].astype(str) # 10. 品类汇总 category_summary ( df.groupby(商品类别) .agg(总销售额(订单金额, sum), 订单量(订单号, count)) .reset_index() )这一套走下来数据已经从“能看但不能用”变成了“可以直接分析的干净表”。中途每步都可以输出看一下检查有没有异常结果。6.3 可视化输出与业务解读聚合好之后画两张核心图月度销售额折线图和品类销售额柱状图。plt.figure(figsize(12, 5)) plt.subplot(1, 2, 1) sns.lineplot(datamonthly, x月份, y月销售额, markero) plt.title(月度销售额趋势) plt.xticks(rotation45) plt.subplot(1, 2, 2) sns.barplot(datacategory_summary, x商品类别, y总销售额) plt.title(各品类销售总额) plt.xticks(rotation45) plt.tight_layout() plt.show()从这个结果中你可以看到月度趋势里哪个月是销售高峰哪个品类贡献了主要收入。再把利润字段按品类聚合就能发现高销售额品类是否也是高利润品类——如果没有那就要考虑定价或成本结构是否存在问题。这就是从“数据清洗到数据分析再到业务结论”的完整闭环。7. 常见问题与排查技巧实录最后整理我平时被问得最多的几个报错和坑做成速查表方便你在出问题时对照排查。7.1 高频报错速查表报错信息出现原因解决办法UnicodeDecodeError读取CSV编码不匹配换gbk、utf-8或gb18030编码逐项尝试KeyError: xxx列名写错或列名里有空格用df.columns查看真实列名注意空格和大小写SettingWithCopyWarning链式赋值的典型警告用.loc操作避免对切片后的DataFrame连续赋值TypeError: unsupported operand类型仍是字符串就做了数值运算先.astype(float)或pd.to_numeric()ValueError: cannot convert float NaN to integer含有空值却转成int先填充空值再转类型或转成float其中我特别想展开说的是 SettingWithCopyWarning。很多新手一看到这个警告就慌其实它意味着你修改的可能不是你想改的那个DataFrame。比如df_sub df[df[订单金额] 500] df_sub[备注] 高价值订单 # 这里很可能触发警告原因是df_sub可能是原始DataFrame的切片视图也可能是副本Pandas的选择行为有时并不明确。最稳妥的写法是df_sub df.loc[df[订单金额] 500].copy() df_sub[备注] 高价值订单copy()强制生成独立副本后续的修改就不会影响原表也不会报警告。7.2 数据清洗的独家避坑心得最后分享几个我自己的操作习惯。每次清洗完一个字段我顺手就会验证一下转换结果比如df[订单金额].dtype应该变成floatdf[订单日期].dtype应该变成datetime64。不要等所有步骤完成再一次性验证出了错要回头定位是哪一步导致的排查成本会高很多。还有个习惯是保留清洗前的原始数据备份。我一般用df_raw df.copy()先存一份清洗流程中如果发现某个转换把数据改坏了还能回头和原始数据做对照。这个习惯在数据量大的项目里非常管用。所谓清洗能力很多时候不是操作多熟练而是你留了多少后路、做了多少验证。我个人体会最深的一点是Pandas的门槛真不高高的是对数据的敏感度。同一份数据摆在两个人面前一个人直接画图出结论另一个人先检查缺失、类型、重复、分布最后画出图来谁的结果更可信一目了然。把清洗到可视化这一条链路理顺了你就已经超过大多数人。以后碰到再复杂的分析项目也不过是往这条链路上加更多细节而已。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询