跳到主要内容 Python 数据可视化实战:Matplotlib 基础与进阶 | 极客日志
Python AI 算法
Python 数据可视化实战:Matplotlib 基础与进阶 如何使用 Python 的 Matplotlib 库进行数据可视化。内容涵盖了环境配置、折线图、直方图、散点图和饼状图的绘制方法,包括颜色设置、标签添加、样式定制及交互模式切换。文章还补充了子图创建、高分辨率保存、性能优化及常见问题排查等进阶技巧,旨在帮助读者掌握 Matplotlib 的基础与核心功能,从而有效展示数据分析结果。
WenxuanMa 发布于 2025/2/7 更新于 2026/4/20 1 浏览可视化是数据分析的核心环节。仅仅收集、处理和分析数据是不够的,还需要将发现以直观的方式展示出来。数据应当讲述一个故事,而缺乏图表的叙述往往显得沉闷。人类主要通过视觉获取信息,正如俗话所说'一图胜千言'。醒目的图片更容易吸引注意力并帮助理解复杂关系。
作为数据科学和机器学习领域最流行的编程语言,Python 提供了丰富的可视化解决方案。本章将重点学习使用最著名的 Python 可视化库 Matplotlib。其他大多数 Python 可视化库(如 Seaborn、Plotly)要么基于 Matplotlib 构建,要么与其有着相似的绘图逻辑。
一、可视化库 Matplotlib 概述 在前面的章节中,我们已经通过 Pandas 简单接触了 Matplotlib。现在,是时候深入研究这个广受欢迎的可视化工具包了。
Matplotlib 库是第一个用于绘制数据图表的主要 Python 库。毫不夸张地说,它是世界上使用最多的 Python 可视化解决方案。Matplotlib 能将数据绘制成不同类型的图表。折线图、柱状图、散点图和直方图等常用图表类型都可以用 Matplotlib 轻松绘制。此外,Matplotlib 还有许多扩展模块可以用来可视化天文、地理或科学数据。
1. 环境准备与导入 Matplotlib 通常随 Anaconda 发行版自带。只需要将其导入文件即可开始使用。新建一个 Jupyter Notebook 文件,然后导入 Matplotlib 的 pyplot 模块:
import matplotlib.pyplot as plt
Matplotlib 是一个庞大的库,我们不需要将其全部导入,这里只需要导入主要的模块 pyplot。为了方便调用,通常将其简写为 plt。
二、折线图 (Line Chart) 我想用一个简单的折线图案例来大致介绍 Matplotlib。首先,用几个数字创建两个 Python 列表:
x = [2 , 5 , 7 ]
y = [2 , 7 , 3 ]
x 变量和 y 变量并不是随机挑选的。为了画线,我们需要把各个点连接起来。每个点的位置都对应着两个数字,也就是 x 坐标和 y 坐标。在这个例子中,一共有三个点。接下来,可以用 Matplotlib 的 plot() 函数绘制折线图:
plt.grid(True )
plt.plot(x, y, marker="o" )
我添加了 plt.grid(True) 函数,是想说明每个点的位置是和它来自 x 和 y 列表的坐标相对应的。此外,我还设置了一个选择性的关键字参数:marker="o",用于表明 plt.plot() 函数是根据我们提供的值来将点连成线的。删去 marker="o" 的话,就只会看到简单的折线了。
如果删去语句结尾处的分号,再重新运行 plt.plot(x,y) 表达式,会看到图标上方有这样一行:[<matplotlib.lines.Line2D at 0x...>]。这是 Python 内存中对绘图对象的引用,在脚本中通常不需要显示。
plt.plot() 函数的用法非常简单。只需要向其中传入任意两个迭代变量,比如列表、元组、Pandas Series 或 NumPy 数组的 x 坐标和 y 坐标,plt.plot() 函数就会绘制折线图。
plt.plot() 函数允许你使用各种各样的样式和颜色。变量实在太多了,以至于 plot 函数表明它能接收 *args 和 **kwargs,也就是说,它可以接收多个参数和关键字参数。把所有可用的标记和样式全部记下来几乎是不可能的。每次需要为图表添加一些花哨的修饰时,我都会运行 help() 函数:
help(plt.plot) 将返回所有可用的图表变量的详情。
1. 颜色与样式 我想先从颜色开始,尝试各种各样的绘图样式。颜色可以以不同的格式传入 plot() 函数。如果是三原色的话,可以用颜色的首字母或完整名称:
plt.plot(x, y, color="b" )
plt.plot(x, y, color="blue" )
plt.plot(x, y, color="r" )
plt.plot(x, y, color="red" )
plt.plot(x, y, color="g" )
plt.plot(x, y, color="green" )
若是你觉得用预设颜色很无聊,可以使用 HEX 或 RGB 格式。推荐使用在线调色板网站查看 HEX 或 RGB 代码。举个例子,如果我想用浅珊瑚色,则需要输入以下代码:
plt.plot(x, y, color="#F08080" )
plt.plot(x, y, color="LightCoral" )
任何图表都需要有图例和标题。Matplotlib 的两个特殊函数:plt.legend() 和 plt.title(),可以用来为图表添加注释。
不用说,所有可用的 Matplotlib 函数都可以通过 dir(plt) 命令查看。
plt.legend() 函数反映了绘图中显示的数据。它的用法很简单,只需在 plot 中添加 label 关键字参数,然后,plt.legend() 函数就会将其呈现出来:
plt.plot(x, y, color="#F08080" , label="Line" )
plt.legend()
图表注释可以放置到图表任意位置。添加代表位置的 loc 参数,并从 Location string 列表中指定位置即可。Location string 列表可以在 help(plt.legend) 返回的函数详情中找到。
我将把 plt.plot() 中的 Line 标签放置在图形的中下方:
plt.plot(x, y, color="#F08080" , label="Line" )
plt.legend(loc="lower center" )
除了图例之外,还可以用 plt.title() 函数为图表添加标题。图表标签应以字符串的形式传入 plt.title() 函数。plt.title() 函数允许我们指定标签的位置、颜色和字号。使用 loc 参数,标签可以被放置在以下三个位置之一:左 (left)、右 (right) 和默认的中心 (center)。为了像 plt.plot() 函数中那样自定义设置标签的颜色,可以传入三原色的名字或 HEX 和 RGB 代码。标签文本的大小应该用 fontsize 关键字来设置。
2. 股票价格图表实战 现在,我想绘制一个股价图表。首先要做的是过去历史股票价格。回到文件的第一个单元格,导入工具库 Pandas-Datareader:
import pandas_datareader as pdr
从雅虎财经获取苹果或其他任意股票在任意日期范围内的历史价格:
data = pdr.DataReader("AAPL" , "yahoo" , "2021-01-01" , "2021-12-12" )
data["Adj Close"] 列将作为 plt.plot() 函数中的 y 参数被绘制在纵轴上。data.index 索引则将代表横轴:
plt.plot(data.index, data["Adj Close" ])
这条绘图语句看起来有些复杂,为了使其更容易懂,我将把 data["Adj Close"] 切片,并将其分配给 y 变量。同时,再将 data.index 分配给 x 变量:
x = data.index
y = data["Adj Close" ]
plt.plot(x, y)
我们增加了两行代码,但这样做是值得的。现在,对于可能会看到这段代码的其他人而言,它非常清晰易懂。此外,在想绘制更多内容时,我们还能更轻松地插入新的数值。
在 plt.plot() 函数中加入 label,并用 plt.legend() 方法在右下角显示这条标签:
plt.plot(x, y, color="#196F3D" , label="AAPL" )
plt.legend(loc="lower right" )
在左边添加一个标题,其颜色与股价折线的颜色相同,再将字号设置为 22:
plt.title("Apple Inc. Stock Price" , loc="left" , color="#196F3D" , fontsize=22 )
运行以上代码,会看到一个美观的图表,带有自定义标题和图例标签。但我对重叠的横轴的值还不是很满意。
Matplotlib 提供的 xticks() 函数和 yticks() 函数可以用来为横轴和纵轴设置自定义标签。在这个例子中,自定义标签很难和 Data.index 值匹配,并且我们将来可能会改变日期范围。所以,为了能看清楚日期,我们要把它们稍微旋转一下。xticks() 函数和 yticks() 函数有一个可以改变文本角度的 rotation 参数。将 rotation 参数设置为 45,可以让 x 标签倾斜 45 度:
我们还可以对图表应用一些其他样式。比如 grid() 函数,其作用是添加任意样式和颜色的网格线:
plt.grid(color="brown" , linestyle=":" )
和许多 Matplotlib 函数一样,grid() 的可自定义程度也非常高。可以设置网格线的颜色和线条样式,还可以通过 figure() 方法设置图表的大小。在 Matplotlib 中,figure 这个词指的是绘制出的数据。图表的大小是用 figsize 关键字来设置的。宽度和高度应该作为列表或元组来传递,大小则以英寸为单位:
plt.figure(figsize=(12 , 8 ))
我的一个学生曾问我是否可以在图表中使用企业指定用的颜色,因为她们公司是这样要求的。答案是肯定的。如你所见,可以为线条或网格设置任何颜色。此外,Matplotlib 还包含 style 包。可以通过调用 plt.style.use() 方法来定义各种各样的风格。我不打算详细介绍如何构建样式,因为这超出了本书涵盖的知识范围。如果出于一些原因而需要设置特定的样式表,可以在 Matplotlib 官方文档找到相关的教程。
对于我这样只是想让图表看起来更时髦一点的人来说,使用预设的样式表是更好的选择。所有可用的预设样式表都可以在 Matplotlib 官方文档中找到。例如,seaborn 这个广受欢迎的样式可以应用于以下这样的图表上:
Python 按顺序运行代码,所以 plt.style.use() 函数和 figure() 函数应该在最开始的 plot() 之前定义。
三、直方图 (Histogram) 直方图是另一种主流的图表类型。和 plot() 函数不一样的是,hist() 方法需要一组数据。直方图经常用来展示数据的分布。
通过苹果股票的历史价格,我们可以计算出该股票的每日回报率,并将其绘制成直方图:
stock_return = data["Adj Close" ].pct_change(1 ) * 100
Pandas 的 pct_change() 方法会返回当前日期和前一天的数据之间的百分比变化。stock_return Series 中的第一个值是 NaN。为了绘制直方图,我们需要把 NaN 这个值删去:
stock_return.dropna(inplace=True )
在 dropna() 方法删去所有的 NaN 后,就可以把这个 Series 作为参数传入 hist() 函数:
传入 hist() 函数中的数据被分割成若干个等宽的 bin。可以用第二个参数 bins 来改变范围,如果观察次数允许的话,可以通过增加 bins 的数量获得更精确的结果:
plt.hist(stock_return, bins=100 )
plt.title("Distribution of AAPL Daily Return" )
除了标题文本外,Matplotlib 还提供了设置横轴和纵轴的标签的选项。正如其名,xlabel() 和 ylabel() 这两个函数的作用是为轴命名:
plt.xlabel("Daily Percentage Return" )
plt.ylabel("Frequency" )
在添加了标题和坐标轴标签后,现在的直方图就完成了。直方图可以保存为 png、jpeg、pdf 或 svg 格式的独立文件。
可以利用 Matplotlib 库的 savefig() 函数生成一个包含图表的全新文件。提供一个文件名作为字符串参数即可:
plt.savefig("AAPL return.png" )
plt.savefig("AAPL return.pdf" )
请记住,savefig() 函数应该是为绘制图表所运行的全部语句中的最后一条 Matplotlib 命令。如果需要保存高分辨率图片,可以添加 dpi 参数,例如 plt.savefig("image.png", dpi=300)。
四、散点图 (Scatter Plot) Matplotlib 库可以使用三种不同的后端。这里,我将称它们为格式。前面用的都是 inline(内联) 默认格式。内联格式生成静态图像并将其存储在 Jupyter Notebook 中。内联格式的主要优势在于,你可以在每个 Jupyter 文件中绘制任意数量的静态图。
若是希望图表具有交互性的话,就需要切换到 notebook(笔记本) 模式。每个 Jupyter 文件中只能有一个交互式图表。因此,请为接下来的练习新建一个文件。在导入 Matplotlib 之前,需要用一个 Python 魔法函数来启动交互模式:
%matplotlib notebook
import matplotlib.pyplot as plt
我称这个函数为魔法函数,并非夸大其词。魔法函数 (magic function) 是 IPython 的官方术语,指的是以 % 符号为前缀的函数。
散点图是数据分析中经常使用的图表之一,我们将用 scatter() 函数来绘制 2019 年的美国人口分布。scatter() 函数不仅可以绘制数据,还可以根据数值来调整点的大小和颜色。
除了绘图库之外,还需要导入 Pandas 库。请将其与 Matplotlib 库一起导入:
%matplotlib notebook
import matplotlib.pyplot as plt
import pandas as pd
含有数据的 Excel 文件已经被上传到网上,可以用 Pandas 库的 read_excel() 函数读取它。文件的第一行是标题,我们可以用 skiprows=1 关键字参数跳过这一行:
data = pd.read_excel("https://example.com/data.xlsx" , skiprows=1 )
一如既往,我们需要对数据进行清洗,只抓取包含信息的那些列:
data = data[["State" , "Population" ]]
data["Population_Mill" ] = data["Population" ] / 1000000
数据的范围太广了,为了让散点图显得整齐一些,我们可以筛选数据,筛出人口在 200 万到 800 万之间的州:
filtered_data = data[(data["Population_Mill" ] > 2.0 ) & (data["Population_Mill" ] < 8.0 )]
scatter() 函数与 plot() 方法很相似,它也将 x 和 y 这两个值用作坐标。为了让代码更加简明,我将对 filtered_data DataFrame 进行切片,并将 filtered_data["State"] 分配给 x 变量,filtered_data["Population_Mill"] 则分配给 y 变量:
x = filtered_data["State" ]
y = filtered_data["Population_Mill" ]
接着将 x 和 y 这两个对象传入 scatter(),并旋转横轴上的州名:
plt.scatter(x, y)
plt.xticks(rotation=90 )
%matplotlib notebook 成功生成了一个交互式图表。通过图下方的菜单可以放大和移动数据。单击软盘图标即可保存。
前面提到过,Matplotlib 库的 scatter() 函数让我们可以通过 s 和 c 这两个关键字参数来控制点的大小和颜色。为了让散点图更加美观,我们可以用 filtered_data["Population_Mill"] 数据指定散点图的大小和颜色。我将通过把数值乘以四次方来放大数据点:
size = filtered_data["Population_Mill" ] ** 4
color = filtered_data["Population_Mill" ]
plt.scatter(x, y, s=size, c=color)
有的点会和其他点重叠,为了提高它们的透明度,还需要添加 Matplotlib 库的另一个样式属性 alpha。alpha 低于 1 时,图表的透明度就会增加:
plt.scatter(x, y, s=size, c=color, alpha=0.5 )
像 Matplotlib 库的所有绘图函数一样,scatter() 允许提供自定义颜色图或者文档中的预设颜色图。在以下网址中可以找到所有颜色图。我选择了 plasma 这个颜色图,并将 cmap="plasma" 属性传入了 scatter() 函数。如果再添加一个显示色阶的颜色栏的话,散点图包含的信息量会更多:
plt.scatter(x, y, s=size, c=color, alpha=0.5 , cmap="plasma" )
plt.colorbar()
我们当然还需要添加标题和纵轴标签。我认为,把 figure 的尺寸从 8 提升到 10 会比较好。在使用 scatter() 之前,需要先在 figure() 函数中定义 figsize。在代码中插入 plt.figure(figsize=(10, 8)):
plt.figure(figsize=(10 , 8 ))
plt.scatter(x, y, s=size, c=color, alpha=0.5 , cmap="plasma" )
plt.xticks(rotation=90 )
plt.title("The States with population estimates between 2 and 8 million, 2019" )
plt.ylabel("Population in millions" )
你可能注意到了,我总是将分号字符移到代码的最后一行。这是为了隐藏 Python 内存中对绘图对象的引用。
这次,我不想在绘图中添加网格线,而是想在每个点上标注其对应的州的名字。
利用 Matplotlib 库的 annotate() 函数,我们能根据 x 坐标和 y 坐标在图表的任何地方放置文本标签。试着用以下代码把 Here 标签放在 Indiana 点上:
plt.annotate("Here" , ("Indiana" , 6.4 ))
x 坐标和 y 坐标应该以元组的形式传递,比如 ("Indiana", 6.4)。"Indiana" 代表横轴上的 x 值,6.4 则是 y 轴上的人口数。
重新运行 Jupyter Notebook 单元格,会看到 "Here" 出现在代表印第安纳州的橙色圆点边上。不过,我们可不想手动添加所有标注。我们可以遍历所有 x 值,通过索引来获取坐标。这需要用到 Python 的内置函数之一:enumerate()。enumerate() 函数的作用是为存储在 x 变量下的 filtered_data["State"] 的所有值提供索引。在 for 循环的帮助下,我们将处理枚举对象,并将每个州的索引和名称传给 annotate() 函数。x 和 y 这两个变量持有 Pandas Series 对象,我们要用 iloc[] 方法将索引与值对应起来:
for index, label in enumerate (x):
plt.annotate(label, (x.iloc[index], y.iloc[index]))
我们创建的交互式散点图允许用户通过菜单中的缩放选项来放大数据,并通过鼠标左键来移动它。菜单中的 home 按钮可以把图表重置为默认尺寸。上面的单元格中设置的 notebook 模式只允许文件有一个图表,因为交互模式有递归的特性。默认的 inline 和交互式的 notebook 格式是 Jupyter 的主要模式。
除了 Jupyter 之外,Matplotlib 还将计算机操作系统用作后台引擎。这可以通过魔法函数 %matplotlib 来实现:
%matplotlib
import matplotlib.pyplot as plt
在这种情况下,Matplotlib 将在一个单独的 Python shell 中生成类似于 notebook 模式的交互式图表。切换 Matplotlib 的模式时,需要记住的一点是,不能同时使用多个模式,如果你在 Jupyter 文件中用一个模式替换了另一个模式,就需要重新启动内核。
五、饼状图 (Pie Chart) 我们将在交互式 shell 中生成饼状图。新建一个 Jupyter 文档,以 %matplotlib 格式导入 Matplotlib:
%matplotlib
import matplotlib.pyplot as plt
这段代码将返回以下内容:Using matplotlib backend: MacOSX。如果使用的是 Windows 操作系统,则会返回 Windows。返回结果中的 Using matplotlib backend 意味着 Matplotlib 已经连接上了操作系统,并用它来生成图表。
延续前面的例子,我们要把美国各地理区域的居民人口绘制成饼状图。美国人口普查局的数据表明,美国有 38.26% 的人口居住在南方,23.87% 居住在西部,20.82% 居住在中西部,17.06% 居住在东北部。
population = [38.26 , 23.87 , 20.82 , 17.06 ]
areas = ["South" , "West" , "Midwest" , "Northeast" ]
Matplotlib pie() 函数将生成一个简单的饼状图。想查看所有可以用来设置饼状图的参数的话,请运行 help(plt.pie)。将人口作为 x 值传入 pie(),并将地区用作标签:
plt.pie(x=population, labels=areas)
Matplotlib 后端引擎会生成一个包含简单饼状图的弹出窗口。
pie() 函数和 Matplotlib 的其他函数都接受自定义颜色。在这个例子中,我决定从一个明亮的调色板中挑选颜色。
palette = ["#00FFFF" , "#FF00FF" , "#00FF00" , "#800080" ]
plt.pie(x=population, labels=areas, colors=palette)
为了说明问题,有时需要将饼状图中的一个扇区突出显示。这可以通过 pie() 函数的 explode 参数实现。explode 参数接受一个可迭代的列表或元组,其中的浮点数表示每个扇区到中心的距离。
举个例子,explode=[0, 0.1, 0, 0] 参数将把第二个扇区从中心推到 0.1。在本例中,我将让 West 扇区显示在与饼状图中心的距离为 0.2 的地方:
standout = [0 , 0.2 , 0 , 0 ]
plt.pie(x=population, explode=standout, labels=areas, colors=palette)
pie() 函数中的另一个样式参数是 shadow。如果想让饼状图有 3D 效果,就要把 shadow 参数切换为 True:
plt.pie(x=population, explode=standout, labels=areas, shadow=True , colors=palette)
除了标签之外,我还想让图中显示出每个区域的确切人口占比。这就是 autopct 参数派上用场的时候了。我们需要把值的格式指定为一个字符串。字符串的格式应该采用 Python 格式样式。比如,%.2f 这个表达式的作用是让小数点后显示两个数字,%.2f%% 则会在值的后面放一个百分号:
plt.pie(x=population, explode=standout, labels=areas, autopct='%.2f%%' , shadow=True , colors=palette)
添加了新的样式属性后,我们成功地生成了一个非常漂亮的饼状图。在生成饼状图的过程中要是出了什么问题,不妨重新启动内核。
当然,可以像前面的例子那样再为饼状图添加一个标题。
六、进阶技巧与最佳实践 Matplotlib 是个用于数据可视化的实用工具,很容易上手。本文介绍了可视化和格式化图表的所有主要功能。我们学会了如何建立基本的图表。但是,利用 Matplotlib 和众多附加功能及插件,能做的事情远远不止于此。
1. 子图 (Subplots) 在一个图形中绘制多个图表是非常常见的需求。Matplotlib 支持通过 subplots() 函数创建多子图布局:
fig, axes = plt.subplots(2 , 2 , figsize=(10 , 8 ))
axes[0 , 0 ].plot(x, y)
axes[0 , 0 ].set_title("Top Left" )
axes[0 , 1 ].scatter(x, y)
axes[0 , 1 ].set_title("Top Right" )
plt.tight_layout()
plt.show()
tight_layout() 函数会自动调整子图参数,使之填充整个图像区域,避免标签重叠。
2. 图像保存优化 在保存图像时,建议指定 bbox_inches='tight' 参数,这样可以自动裁剪掉多余的空白区域,确保导出的图片紧凑且专业:
plt.savefig("final_plot.png" , bbox_inches='tight' , dpi=300 )
3. 性能优化 当处理大量数据点时,Matplotlib 可能会变慢。此时可以考虑使用 agg 渲染器或者减少点的数量。对于超大规模数据集,建议使用 Datashader 等专门针对大数据可视化的库。
4. 常见问题排查
中文乱码 :需要在代码开头设置字体,例如 plt.rcParams['font.sans-serif'] = ['SimHei']。
图片不显示 :检查后端设置,确保使用了正确的 %matplotlib 指令。
样式不生效 :确认 plt.style.use() 在绘图命令之前执行。
要想进一步了解更复杂的样式和图表,可以访问 Matplotlib 官方文档库页面,那里有海量的示例和 API 参考。
学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。掌握数据可视化技能对于从事数据分析、人工智能相关工作至关重要。通过系统性地练习上述图表类型,你将能够构建出既美观又专业的数据报告。
相关免费在线工具 加密/解密文本 使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
RSA密钥对生成器 生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
Mermaid 预览与可视化编辑 基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
curl 转代码 解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online