用Python绘制二维图:从选型到避坑的完整指南

📅 发布时间:2026/10/9 18:32:34
用Python绘制二维图:从选型到避坑的完整指南
做数据分析的人手里天天转的不外乎两类东西表格和图。表格负责精确图负责直观。而二维图就是这里面最基础也最常用的一类——把两个维度的数据放进一个平面坐标系用点、线、柱子的位置和形状把规律直接画给人看。不管是做业务报表、写竞品分析还是给领导汇报项目进展最后能打动人的往往不是那串数字而是那张一眼就能看懂规律的图。这篇文章写给刚接触数据可视化、或者已经会用Excel画图但想更进一步的人。我会从先选对图的思路、代码实现过程、常见坑和排查经验三个层面把二维图这件事拆开讲清楚。全程用真实可跑的代码示例配合我自己踩过的坑。你不需要多深的编程底子能装Python环境、能看懂基础语法就能跟着做出一张能直接放进周报里的图。1. 二维图到底解决什么问题1.1 从看图说话到用图决策二维图的本质很简单一张坐标系两根轴一组图形元素。横轴通常是自变量纵轴是因变量中间的点、线、柱、面承载数据本身。很多人觉得画图就是把Excel里的插入图表点一下其实远不止操作层面的差异关键在于——图是一个压缩信息的工具。我给你举个例子。某零售连锁门店的月度销售额如果只看Excel表格你得一行一行盯才能发现三月为什么掉了四月为什么又起来了这些数字在你的脑子里是离散的你需要自己脑补它们之间的连续关系。但画成折线图所有的起伏顺序都摆在你面前。哪个是拐点、哪个是峰值、哪个是异常回落一秒钟内就能定位。这不是玄学是图形编码帮你的大脑省了翻译表格的时间。我自己在给团队做复盘时特别看重看图之后能不能直接给出决策。比如某电商运营团队的数据报表里广告投放金额和销售额是不是真的有正相关关系是强相关还是弱相关看表格你只能大概说好像有关系画一张散点图加上趋势线相关系数直接写进图里结论就非常硬。这就是二维图从看图说话进化到用图决策的过程。1.2 二维图的适用边界不过我要泼一盆冷水二维图不是万能的。它最适合表达四类信息趋势、对比、分布、相关关系。超过这个范围它的优势会迅速衰减。具体来说如果数据维度很高比如一个用户有年龄、性别、消费频次、客单价、活跃天数、来源渠道、设备类型等十五个字段想全部塞进一张二维图里那画面会很灾难。你只能降维要么选两个最重要的维度画二维图要么用主成分分析之类的办法先压缩维度。如果数据是个体明细比如十万条订单记录全部用散点图铺出来只会得到一团密集的墨点什么都看不出来这时候更应该做聚合画直方图或者统计摘要。我见过最典型的错误用法是有人把一张200行的明细表全部做成了柱状图X轴上密密麻麻排了两百根柱子每根柱子上还贴了数值标签。结果就是谁也看不清谁也不想看。二维图是沟通工具不是存储工具。数据的精读应该留给表格图的价值在于把最有价值的那一两个结论放大给观众看。记住这个边界后面选图、画图时才有判断依据。2. 先选对图再谈画图2.1 八种常见二维图的应用场景很多人一打开画图工具就默认选折线图或柱状图也不管数据长什么样。这里我把日常工作中最常用的八种二维图按场景整理了一遍。折线图最经典的时间序列图适合展示一个或多个指标随时间的变化。注意时间轴要连续如果中间有缺失要么插值要么在图上明确标注缺口不要让人误以为数据是连续的。柱状图适合做类别对比比如各门店的销售额、各品类的库存周转天数。柱子的高度代表数值大小人眼对高度差非常敏感。画柱状图时柱子要从坐标轴原点开始不要截断否则会夸大差异。条形图把柱状图转90度适合类别名称很长的情况。比如省市区名称、商品标题横排才能放下可读性比竖排高很多。散点图两列数值型数据的黄金搭档专门用来观察两组数据之间的相关关系。比如广告投入和销售额、使用时长和次日留存率。我通常会顺手加一条拟合线让趋势更明显。面积图可以理解成折线图的加粗版强调累积量和变化速度。适合展示各渠道流量的构成变化但多个序列叠加时要注意顺序和透明度否则会互相遮挡。饼图/环形图只适合展示简单的占比结构且类别越少越好。超过五六个类别就用堆叠柱状图替代否则小扇区几乎无法区分。箱线图不怕离群值干扰适合看数据的分布形态比如不同渠道的用户消费分布。盒子代表四分位区间中间的线是中位数外面的须和点代表极值一张图就能看出分布是对称还是偏斜。直方图注意它和柱状图的区别。柱状图的横轴是类别直方图的横轴是数值区间。直方图用来观察单一变量的分布规律比如订单金额集中在哪个区间。2.2 一张表分清选型逻辑我整理了一张速查表每次拿不定主意时就对照它我想表达什么推荐图关键注意点随时间变化的趋势折线图、面积图时间轴连续缺失点要标注类别之间比大小柱状图、条形图从零刻度开始柱宽一致两个数值变量的关系散点图 趋势线样本量太少时别强行拟合整体构成占比饼图、堆叠柱状图类别超过6个就放弃饼图数值的分布形态直方图、箱线图分箱数量影响结论需调试多个部分与整体堆叠柱状图、瀑布图注意堆叠顺序和基准线的可读性这张表看似简单但真到了项目汇报前很多人还是会选错。我自己的习惯是先问自己我要给观众什么结论再回头对照这张表。选图的本质是匹配信息目标和图形编码不是看哪个图好看。2.3 选型背后的三个判断标准除了上面的速查表我还会用三个标准来验证自己的选型是不是合理。第一个标准你要传递的结论属于变化、比较、分布、关联里的哪一种。这个问题问清楚了至少能排除一半错误选项。比如你的结论是销售额同比上升了18%这是比较柱状图更合适如果你的结论是销售额在三个月内呈现出持续上升的趋势这是变化折线图更合适。第二个标准数据的规模和形态。数据点是20个还是2万个直接影响图形元素的选择。20个点可以一根一根柱子画清楚2万个点就必须考虑聚合、采样或者换用hexbin这类密度图。数据太稀疏时散点图会变成几个孤零零的点没有说服力。第三个标准观众的熟悉程度。给技术团队做分享散点图加拟合线、箱线图都没问题给业务部门做汇报折线图、柱状图永远是最稳妥的选择不是因为它们高级而是因为大家一看就懂不需要额外解释图例和坐标轴的含义。图表是沟通工具优先级永远是信息被接收到高于图自己很酷。3. 实操用代码画一张能直接用的二维图3.1 准备工作与数据形态选型定下来之后进入实操环节。我下面的代码全部基于Python生态核心是matplotlib辅以pandas和numpy。为什么选matplotlib而不是其他可视化库原因有三一是它的生态最成熟任何画图需求几乎都能找到对应接口二是它的可控性极强小到刻度字体都能自定义三是它和pandas无缝衔接从DataFrame直接取列就能画这在数据分析工作流里太方便了。安装很简单一行命令pip install matplotlib pandas numpy画二维图之前先把数据整理成两列的标准形态。一列作为横轴一列作为纵轴。横轴可以是日期、类别名、数值纵轴就是你要观察的指标。下面我基于一个模拟场景来演示某零售门店连续六个月的销售额以及每个月的广告投入额数据我已经写死在代码里方便你直接复制运行。3.2 从折线图开始先跑通再调样式先画最基础的折线图把月度销售走势展示出来。import matplotlib.pyplot as plt months [1月, 2月, 3月, 4月, 5月, 6月] sales [128, 142, 136, 158, 167, 189] plt.figure(figsize(10, 6)) plt.plot(months, sales, markero, linestyle-, linewidth2, color#2E86AB) plt.title(某零售门店月度销售额走势) plt.xlabel(月份) plt.ylabel(销售额万元) plt.grid(axisy, linestyle--, alpha0.4) plt.tight_layout() plt.show()这段代码里markero把每个数据点标成圆点不然折线图看起来很虚只有一条线而没有数据锚点grid(axisy, linestyle--, alpha0.4)只给Y轴加淡淡的虚线网格方便横向比高度又不会抢视觉焦点tight_layout()自动调整边距避免坐标轴标题被截掉。跑通之后你会发现一个问题三月份销售额从142万掉到136万这个回落如果不特意去盯很容易被整体上升的趋势掩盖。这时候就要加标注了。我通常用annotate把异常点和结论直接写进图里plt.annotate(3月回落4%, xy(2, 136), xytext(2.4, 122), arrowpropsdict(arrowstyle-, color#666), color#333, fontsize10)3.3 柱状图与堆叠场景对比与构成折线图适合看趋势但要做各品类之间谁高谁低这种对比柱状图更有力量。我们还是用同一个数据源改成不同渠道的订单结构对比。import matplotlib.pyplot as plt categories [A类, B类, C类] online [30, 42, 28] # 线上渠道订单量万单 offline [48, 35, 52] # 线下渠道订单量万单 plt.figure(figsize(8, 5)) plt.bar(categories, online, label线上渠道, color#2E86AB) plt.bar(categories, offline, bottomonline, label线下渠道, color#F18F01) plt.ylabel(订单量万单) plt.title(各品类订单渠道构成对比) plt.legend() plt.tight_layout() plt.show()这里最关键在于bottomonline。堆叠柱状图的底层是线上渠道第二层离线渠道需要从第一层的顶部开始画所以把bottom参数指定为第一层的数据数组。很多人画堆叠图总画成两排并列的柱子就是因为漏了这一步。顺序也有讲究建议把占比比较稳定、数值比较小的类别放到底层这样顶部线条的波动主要反映大类变化读图时更有条理。如果横向类别名太长比如母婴用品和数码家电这类词用plt.barh画横向条形图标签可读性会明显更好。3.4 散点图与趋势洞察发现隐藏关系散点图是我个人最常用的一类二维图尤其做相关性分析时。下面这个例子看广告投入和销售额之间有没有线性关系。import matplotlib.pyplot as plt import numpy as np x [2, 3, 4, 5, 6, 7, 8, 9, 10] # 广告投入千元 y [3.1, 4.2, 5.0, 5.8, 7.2, 7.9, 9.1, 9.8, 11.2] # 销售额万元 fig, ax plt.subplots(figsize(8, 5)) ax.scatter(x, y, s60, alpha0.8, color#D64933, label实际数据) # 一元线性拟合画出趋势线 z np.polyfit(x, y, 1) p np.poly1d(z) ax.plot(x, p(x), --, color#555, linewidth1.5, label拟合趋势线) ax.set_xlabel(广告投入千元) ax.set_ylabel(销售额万元) ax.set_title(广告投入与销售额的关系) ax.legend() plt.tight_layout() plt.show()alpha0.8控制点的透明度当点很多、相互重叠时透明度能让密集区域颜色更深稀疏区域颜色更浅密度信息自然呈现。s60控制点的大小点的大小本身也可以编码第三个维度但新手不建议过度使用宁可用颜色做辅助维度。np.polyfit(x, y, 1)做的是最小二乘线性拟合返回一次多项式的系数np.poly1d把它包装成可以直接调用的函数。趋势线的价值在于就算数据点很散观众也能顺着那条虚线看到整体方向。但注意拟合线只适合在样本量足够且有实际意义时使用如果只有三五个点硬画一条趋势线很容易误导人。3.5 让图表能上台面的细节处理代码跑通只是第一步真正能放进周报或者汇报PPT里的图细节必须经得起看。我总结了几个必调的细节。先解决中文字体。matplotlib默认字体不支持中文直接显示方块乱码。最简单的方案是在画图脚本开头统一配置plt.rcParams[font.sans-serif] [SimHei, Microsoft YaHei, PingFang SC] plt.rcParams[axes.unicode_minus] False第一行指定中文字体候选列表按系统可用字体依次匹配第二行是关键中的关键——关闭Unicode负号否则坐标轴上的负号会显示成方块。这两行配置放在脚本最顶部全局生效省去每张图单独设置字体的麻烦。然后是坐标轴范围和刻度。matplotlib默认会根据数据自动扩展坐标轴但这不一定是最好的呈现方式。比如数据范围是[120, 190]自动坐标轴可能会从100开始留出一大段空白看起来曲线很平缓。我会手动设置plt.ylim(0, 220)既保持从零开始的诚实感又压缩多余空白。导出时建议设置高分辨率plt.savefig(report_chart.png, dpi300, bbox_inchestight)dpi300保证打印和投屏都清晰bbox_inchestight自动裁掉四周多余白边避免导出后图片四周一大片空白。需要继续编辑的场合导出SVG矢量格式更好缩放不失真。4. 新手最容易踩的坑与排查实录4.1 Y轴非零起点造成的比例错觉这是二维图里最经典的误导陷阱。Excel默认有时会从接近最小值的刻度开始而不是从0开始。比如两组柱子的高度分别是100和105如果Y轴从90开始两根柱子的视觉高度差会扩大成5倍让人误以为差距很大。而事实上只差了5%。判断标准很简单柱状图、条形图这类依赖长度编码的图Y轴必须从0开始否则长度比例被扭曲。折线图相对宽松因为折线图编码的是位置和斜率为了看清波动细节从非零起点开始是可接受的但必须明确标注断轴记号并且告诉观众这里不是从零开始的。我在实际汇报里见过太多次数据没错但因为坐标轴起点问题被领导质疑最后不得不重画。诚实比好看重要。4.2 图例和颜色别让观众做选择题颜色滥用是另一个高频问题。一张图上超过六个系列还各用一个颜色观众要不停对着图例来回找等于在做连线题。我的经验是系列控制在三个以内时用不同颜色区分没问题超过三个系列优先考虑把不重要的合并成其他或者改用分面图每张图只画一个系列并排放置。颜色本身也要考虑色盲人群。红绿搭配是最常见的错误红绿色盲人群分不清。稳妥的做法是选用色盲友好的调色板或者在同一张图里同时用颜色线型/形状双重编码。比如一条红色实线和一条绿色虚线变成立备选方案。4.3 数据量过大时的渲染卡顿如果你画过几万个点的折线图就会知道matplotlib直接画会卡到怀疑人生。十万个点的折线线条互相重叠渲染慢图面也糊成一团。我的处理思路分三步。第一步先判断是否需要展示全部细节。如果是看整体趋势用降采样就够了取每N个点保留一个或者按时间窗口聚合。比如分钟级数据聚合成小时级趋势信息基本保留显示量大幅下降。第二步如果是观察分布而非精确数值用hexbin画六边形密度图。ax.hexbin(x, y, gridsize30, cmapYlOrRd)能把几十万个点压成一张密度热力网格颜色越深代表该区域点越多信息量一点不少。第三步如果必须展示全部点那就不要用屏幕渲染直接导出高分辨率矢量图再交给查看器去缩放。4.4 中文乱码与负号显示异常中文乱码几乎是每个新手必经的坑。前面已经给出了解决方案这里补充排查思路。如果配置了字体还是乱码先确认系统里有没有对应字体。Windows一般有SimHei或Microsoft YaHeimacOS一般有PingFang SCLinux要看有没有安装中文字体包没有的话apt install fonts-noto-cjk这类命令装上就行。还有一种情况是图例里的中文正常但标题里的中文有问题大概率是因为标题用了英文字体栈导致中文字体缺失。统一在rcParams里配置就好。负号显示成方块十有八九是忘了axes.unicode_minus False这个参数只控制负号的编码方式不会影响数据本身。4.5 时间数据的处理细节时间作为横轴时坑也不少。直接从Excel读进来的日期往往是字符串比如2024/01/05直接画图会被当成类别而不是连续时间。正确做法是用pandas.to_datetime先转成datetime类型import pandas as pd df[date] pd.to_datetime(df[date])转完之后matplotlib会自动把日期轴排布成合理的刻度间隔。如果需要控制刻度间隔比如每周一个刻度用matplotlib.dates里头的MonthLocator或WeekdayLocator来设置。时间轴最大的问题是缺失日期。如果数据缺了几天折线图会把缺口直接连起来看起来数据连贯实际上已经断层。要么用dropna配合重采样把缺失日期补齐为NaN要么在图上明确标注数据缺失的时间段。5. 让二维图真正有说服力的进阶心得5.1 标注与比较的学问图表的最高级用法不是展示数据而是展示结论。怎么把观众的目光引到你想要的结论上答案就是标注。我常用的标注有四种。一是峰值标注比如plt.annotate(最高点 189万, xy(5, 189), xytext(4.2, 200), arrowprops...)直接指向最高点观众一眼就知道重点在哪。二是异常点标注数据里突然跳出来的离群值如果不标大家会自己乱猜原因标上此处因系统迁移导致下跌结论就清清楚楚。三是基准线比如在目标值位置画一条水平虚线ax.axhline(y150, colorgray, linestyle--)实际值和目标值的差距立现。四是差异标注两组数据对比时在差值最大的位置标出具体比例让观众直接看到最大差距发生在哪里。标注的原则是少而准。一张图上到处是箭头和文字等于没有标注。每一处标注都要回答一个问题这个位置为什么值得看5.2 做图前的自查清单我每次出图前都会过一次自查清单这里分享给你。第一坐标轴有没有标题和单位很多人画完图忘记写单位销售额是万元还是亿元不写清楚图就废了。第二数据来源和口径有没有注明图下方的注释写一行数据来源内部报表2024年1-6月就能堵住很多质疑。第三结论有没有用标注或标题点出来图表的标题不要说月度销售额图要说月度销售额持续上升3月出现异常回落直接把结论放进标题里。第四配色是不是超过三四种超过就合并系列。第五导出分辨率够不够PPT和打印场景用300dpi屏幕用150dpi。第六最关键的一条——这张图有没有误导人Y轴起点、堆叠顺序、采样方式任何一个环节都可能让图表失真发出去之前自己先盯着看十秒钟问一句如果我不了解数据看了这张图会得出什么结论。自查列表看起来繁琐但你会在几次之后形成条件反射最后画一张图也就多花几十秒。5.3 提升效率的小习惯画图多了之后重复劳动越来越多。我现在有一套固定的效率习惯分享出来给你参考。把样式配置封装成一个函数或独立的样式脚本统一字体、配色、网格风格。这样同一批图表天然风格一致不用每张图重新调参数。把常用的画图逻辑做成函数比如plot_line(df, x_col, y_col, title)输入DataFrame列名就出图。项目数据一变调用同一个函数就重新生成省去复制粘贴的麻烦。色彩方面我习惯提前定好一组品牌色比如主色、辅色、强调色、警示色各一个所有图都用这组色板避免每张图随手抓颜色导致风格不统一。还有一个容易被忽略的点数据文件命名和图表输出路径要规范。我习惯把每个项目的图和原始数据放在同一个目录下图名包含日期和指标名比如sales_trend_20240101.png这样后续找图、归档、复现都非常方便。别小看这些细节项目一多乱七八糟的命名会让你翻半天找不到图。我做二维图这些年最大的体会是画图这件事想清楚要告诉别人什么比练熟任何画图工具都重要。工具只是执行判断才是核心。你在动手调颜色之前先花五秒钟问自己——这张图要传递的唯一结论是什么问完这个问题90%的图形问题其实已经解决了。剩下的只是选择最诚实的那种画法把结论清清楚楚端到观众面前。