Altair Circle 标记完全指南:mark_circle 用法、size 属性与散点图实战
2026/9/24 15:22:10 网站建设 项目流程
  • 数据可视化

【免费下载链接】altair

Declarative visualization library for Python

项目地址:https://gitcode.com/gh_mirrors/al/altair
点击查看免费下载

导读

本文围绕 Altair(声明式 Python 可视化库)中circle标记展开,系统讲解mark_circle()的用法、circle标记与point标记的区别、专用属性size的语义,并结合仓库源码与真实示例给出可复跑的散点图代码。读完本文,你将掌握如何用mark_circle()快速绘制散点图、气泡图,理解其填充与尺寸的底层行为,并能进一步结合size/color/tooltip等编码通道做出更丰富的可视化。


1. circle 标记是什么

Altair 官方文档在 circle.rst 中开宗明义地定义:

circle标记与point标记相似,区别在于:(1)shape的值永远被固定为circle;(2) 默认情况下它们是填充(filled)的。

这句话点出了circle的本质——它是point的一种“特化形式”。散点图中最常见的用法就是把一个数据点画成一个实心圆点,这正是circle标记的定位。

与它形成对照的是 point.rst 中描述的point标记:

默认情况下,point标记只有边框、内部是透明的;可以通过设置filled=True来创建填充的点。

也就是说:

对比项point标记circle标记
shape 取值可自由指定(circle、square、cross、diamond、triangle 等)固定为circle
默认填充不填充(仅描边)填充
典型用途需要形状编码或描边样式通用散点图、地图上的地理点

这一默认行为在 Vega-Lite 模式定义中也有据可查。core.py 中对filled属性写道:

默认值为:pointlinerule标记以及 graticule 数据源的geoshape标记为false;其余情况为true

circle不在此列,因此其filled默认值为true,即实心圆点。


2. circle 标记的属性体系

一个circle标记定义可以包含所有 标准标记属性(如coloropacitystroketooltip等),外加以下这个专有属性:

2.1 专有属性:size

属性类型说明
size数值 / 表达式引用(ExprRef标记的默认尺寸

size的确切语义在源码的MarkDef模式定义(core.py)中有详细注释:

对于point/circle/squaresize表示标记的像素面积。注意该值设置的是符号的面积,其边长会随该值的平方根增长。 对于bar,它表示条带的像素宽度;对于text,它表示字体大小(像素)。

这是一个容易踩坑的细节:size不是“半径”也不是“直径”,而是面积。若想让圆点看起来大一倍,需要把size乘以 4(面积增大为 4 倍、直径才增大为 2 倍),而不是乘以 2。由于面积与边长是平方根关系,size的数值跨度往往较大(常见取值从几到几百)。

2.2 标准标记属性

size外,circle同样支持MarkDef中定义的标准属性,例如(依据 core.py 的 MarkDef 文档):

  • color:默认填充颜色,默认值"#4682b4"fill/stroke的优先级高于color
  • opacity:整体透明度;
  • fillOpacity:填充透明度,默认1
  • stroke/strokeWidth/strokeOpacity:描边颜色与宽度;
  • tooltip:是否显示提示信息(可传True或字段定义);
  • cursorhrefaria等辅助属性。

这些属性既可以作为关键字参数直接传入mark_circle(),也可以在encode()中映射到数据字段,实现按数据取值动态变化。


3. 源码级解析:mark_circle 是如何实现的

mark_circle()Chart对象上的方法,定义在 mixins.py:

@use_signature(_MarkDef) def mark_circle(self, **kwds: Any) -> Self: """Set the chart's mark to 'circle' (see :class:`MarkDef`).""" copy = self.copy(deep=False) # type: ignore if any(val is not Undefined for val in kwds.values()): copy.mark = core.MarkDef(type="circle", **kwds) else: copy.mark = "circle" return copy

从源码可以看到两条实现事实:

  1. 浅拷贝非原地修改:方法返回的是当前图表对象的一份浅拷贝(self.copy(deep=False)),并在这份拷贝上设置mark,因此不会污染原图表对象,也支持链式调用。
  2. 两种底层表示
    • 当没有传入任何标记属性(如mark_circle())时,mark被设置为字符串"circle"——Vega-Lite 的最简简写形式;
    • 当传入了任意属性(如mark_circle(size=50))时,mark被构造为core.MarkDef(type="circle", **kwds)模式定义对象。

也就是说,mark_circle(size=50, color="steelblue")最终会被序列化为{"mark": {"type": "circle", "size": 50, "color": "steelblue"}}这样的 Vega-Lite 规范。这种“无参用简写、有参用 MarkDef”的设计,保证了生成规范的精简与可读。

顺带一提,mark_circlemark_pointmark_square等共享同一套_MarkDef签名机制(@use_signature(_MarkDef)),因此 IDE 中会得到完整的参数提示,类型上则统一走 core.py 的MarkDef模式包装类。


4. 实战:用 circle 标记绘制散点图

原文档给出的最小可运行示例是汽车数据集上的散点图。为了与原文档保持一致且保证可复现,建议使用当前仓库的 datasets 接口获取数据 URL:

import altair as alt from altair.datasets import data source = data.cars.url alt.Chart(source).mark_circle().encode( x=("Horsepower:Q"), y=("Miles_per_Gallon:Q"), )

代码要点说明:

  • data.cars.url返回cars数据集的远程 URL(字符串),无需本地文件;当前仓库的 datasets 模块(altair/datasets/init.py)支持data.cars()直接加载为 DataFrame、data.cars.url获取地址,并可指定engine="polars"/"pandas"/"pyarrow"等后端;
  • xy使用带类型后缀的简写字段描述"Horsepower:Q"(Q 表示定量/连续数据)与"Miles_per_Gallon:Q"
  • mark_circle()不传任何参数,此时底层mark会被简写为字符串"circle"

运行后即可得到一张“马力(Horsepower)对每加仑英里数(Miles_per_Gallon)”的散点图,每个观测点渲染为一个默认填充的实心圆点。

4.1 指定 size 属性

若想控制圆点大小,直接传入size(像素面积):

alt.Chart(source).mark_circle(size=100).encode( x="Horsepower:Q", y="Miles_per_Gallon:Q", )

仓库测试中也有同样的用法,例如 deviation_ellipses.py 中的mark_circle(size=50, tooltip=True)

4.2 结合 size 通道绘制气泡图

把第三个字段映射到size编码通道,散点图就升级为气泡图:

alt.Chart(source).mark_circle().encode( x="Horsepower:Q", y="Miles_per_Gallon:Q", size="Acceleration:Q", )

此时圆点面积随Acceleration字段取值连续变化,这与mark_circle(size=100)的固定尺寸不同:前者是数据驱动的编码通道,后者是标记的固定默认值。仓库中的 gapminder_bubble_plot.py 正是这类气泡图的完整范例。

4.3 叠加颜色与透明度

circle支持所有标准标记属性,例如按分类字段着色、设置透明度以便观察重叠点:

alt.Chart(source).mark_circle(opacity=0.6).encode( x="Horsepower:Q", y="Miles_per_Gallon:Q", color="Origin:N", )

其中opacity=0.6作为标记属性固定透明度,color="Origin:N"将产地(名义型字段)映射为颜色。在点密度高的散点图中,适度降低透明度能有效缓解点与点的遮挡问题;仓库示例 interval_selection_map_quakes.py 就使用了mark_circle(opacity=0.35, tooltip=True)


5. circle 与 point、square 的取舍

  • circle vs point:需要保持圆形、且想要默认填充时优先用circle;需要给不同类别分配不同形状(如正方形、三角形、菱形)时,必须用point并映射shape通道(参考 point.rst 中的形状列表)。
  • circle vs square:二者是“同构”关系——都固定形状、默认填充,唯一区别是几何形状本身。mixins.py 中mark_squaremark_circle的实现完全对称,均按“无参简写字符串、有参构造 MarkDef”的规则生成。选择依据纯粹是视觉语义。

6. 延伸:circle 在地理可视化中的典型应用

由于circle固定为圆形且默认填充,它常被用来渲染地理点。在 point.rst 的 Geo Point 示例中,mark_circle配合longitude/latitude通道与投影即可在地图上标出机场位置:

import altair as alt from altair.datasets import data airports = data.airports() states = alt.topo_feature(data.us_10m.url, feature="states") background = alt.Chart(states).mark_geoshape( fill="lightgray", stroke="white" ).properties(width=500, height=300).project("albersUsa") points = alt.Chart(airports).mark_circle( size=10, color="steelblue", ).encode( longitude="longitude:Q", latitude="latitude:Q", tooltip=["name", "city", "state"], ) background + points

这里mark_circle(size=10, color="steelblue")固定了圆点面积与颜色,tooltip展示机场信息,background + points则利用图层叠加把圆点绘制在美国州界底图之上。仓库中的 airport_connections.py 与 groupby-map.py 也展示了mark_circle在地理/分组地图中的更多组合方式。


7. 小结

  • circlepoint的特化:shape固定为circle,默认填充,适合散点图与地理点图;
  • 专有属性size表示像素面积而非半径,调整视觉大小需按平方关系换算;
  • mark_circle()无参时生成简写字符串"circle",有参时构造MarkDef(type="circle", **kwds)(见 mixins.py);
  • 通过size/color/opacity/tooltip等编码通道,可将散点图扩展为气泡图、着色散点图与交互式地图点层,仓库 tests/examples_arguments_syntax 目录下有大量可直接借鉴的完整示例。

若需进一步了解标记属性的完整清单,可查阅 marks 索引文档 与 core.py 中MarkDef的完整参数文档。

  • 数据可视化

【免费下载链接】altair

Declarative visualization library for Python

项目地址:https://gitcode.com/gh_mirrors/al/altair
点击查看免费下载

相关推荐

上一篇:Claudia MCP服务器管理:统一配置Model Context Protocol
下一篇:3步搞定Wan2.2视频生成模型本地部署,AI视频创作一键开启

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

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

立即咨询