惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Secure Thoughts
博客园_首页
IT之家
IT之家
Engineering at Meta
Engineering at Meta
量子位
宝玉的分享
宝玉的分享
MyScale Blog
MyScale Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
L
LangChain Blog
爱范儿
爱范儿
WordPress大学
WordPress大学
F
Full Disclosure
T
Tailwind CSS Blog
GbyAI
GbyAI
Recorded Future
Recorded Future
美团技术团队
S
SegmentFault 最新的问题
A
About on SuperTechFans
小众软件
小众软件
云风的 BLOG
云风的 BLOG
人人都是产品经理
人人都是产品经理
Recent Announcements
Recent Announcements
Google DeepMind News
Google DeepMind News
Apple Machine Learning Research
Apple Machine Learning Research
D
DataBreaches.Net
J
Java Code Geeks
The Cloudflare Blog
The GitHub Blog
The GitHub Blog
Hugging Face - Blog
Hugging Face - Blog
D
Docker
Vercel News
Vercel News
H
Help Net Security
博客园 - 叶小钗
B
Blog
阮一峰的网络日志
阮一峰的网络日志
N
Netflix TechBlog - Medium
Blog — PlanetScale
Blog — PlanetScale
腾讯CDC
Microsoft Security Blog
Microsoft Security Blog
V
Visual Studio Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 司徒正美
The Register - Security
The Register - Security
aimingoo的专栏
aimingoo的专栏
博客园 - 聂微东
月光博客
月光博客
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Last Week in AI
Last Week in AI
M
MIT News - Artificial intelligence
Jina AI
Jina AI

中文博客 on 范叶亮 | Leo Van

多智能体系统 (Multi-Agent System) 确定性和掌控欲 - 你的 AI 不是你的 AI LLM Token 消耗节省计划 (How to Save Token for LLM) 智能体的角色定位和身份演化 (Agent Role Orientation and Identity Evolution) 本地部署 OpenClaw,QwenPaw 和 Hermes Agent (Local Deployment of OpenClaw, QwenPaw and Hermes Agent) 本地部署智能体 - OpenClaw,QwenPaw,Hermes Agent ... 部署 Matrix 服务器 Synapse (Deployment of Matrix Server Synapse) 部署 frp 内网穿透服务 (Deployment of frp NAT Traversal Service) 本地部署大模型服务 (Local Deployment of LLM Services) AI 时代的生产力和生产关系 (Forces and Relations of Production in AI Era) 业余无线电入门 - CQ, CQ, CQ, this is BD1CZP. Calling CQ and standing by. 重构 - 之于代码、之于工作、之于生活 大语言模型微调 (Fine-tuning Large Language Models) 提升图片分辨率和质量 - Invoke AI 101 教程 使用画布创建和组合生成新的图片 - Invoke AI 101 教程 探索 AI 模型和概念适配器 - Invoke AI 101 教程 理解图像到图像和降噪过程 - Invoke AI 101 教程 使用控制层和指示控制图片的生成 - Invoke AI 101 教程 使用 Invoke 创作你的第一张图片 - Invoke AI 101 教程 在 OpenWrt 和群晖中自动申请和部署证书 凡人歌 - 凡人,但不要烦心 Shell 调用方式 fork,exec 和 source (Run Shell with fork, exec and source) 重定向和管道 (Redirect and Pipe) 模型压缩和推理加速 (Model Compression and Inference Acceleration) 我们需要多少种编程语言 (How Many Programming Languages do We Need) 从 rm -rf * 说起 - 喜新、怀旧、再出发 当我谈摄影时,我谈些什么 - 色彩篇 Part 1 CSS 布局和定位 (CSS Layout and Position) 当我谈修图时,我谈些什么 - 色彩篇 Part 1 在 Windows 下利用 WSL2 和 Ubuntu 配置 GPU 机器学习环境 文学编程和可重复性研究 (Literate Programming and Reproducible Research) 在 OpenWrt 中安装 Jellyfin 搭建家庭影音中心 自私和贪婪 (Selfish and Greedy) 评分和排名算法 (Rating & Ranking Algorithms) 小记这一波裁员浪潮 基于内容的图像检索 (Content-based Image Retrieval, CBIR) 你所应该知道的 A/B 测试 (A/B Test You Should Know) 一个人的摩旅 (Travel with My Motorcycle Alone) 设计语言初探 (A Glimpse of Design Language) Spark 集群搭建 (Spark Cluster Setup) Hive 安装和配置 (Hive Setup) Hadoop 集群搭建 (Hadoop Cluster Setup) 虚拟环境准备 (Virtual Environment Preparation) 大数据 SQL 性能调优 (Big Data SQL Performance Tuning) SQL 样式指南 (SQL Style Guide) 进程,线程和协程 (Process, Thread and Coroutine) - 实现篇 进程,线程和协程 (Process, Thread and Coroutine) - 理论篇 胶囊网络 (Capsule Network) 投票公平合理吗? 图存储与计算 (Network Storage and Computing) - 复杂网络系列 网络算法 (Network Algorithms) - 复杂网络系列 真实世界网络结构 (Structure of Real-World Network) - 复杂网络系列 网络表示,测度和度量 (Network Representation, Measures and Metrics) - 复杂网络系列 文本相似度 (Text Similarity) 而立之前 (Life before 30) 最近邻搜索 (Nearest Neighbor Search) 无模型策略预测和控制 - 时序差分学习 (Model-Free Policy Prediction and Control - Temporal Difference Learning) - 强化学习系列 无模型策略预测和控制 - 蒙特卡洛方法 (Model-Free Policy Prediction and Control - Monte-Carlo Learning) - 强化学习系列 利用动态规划求解马尔可夫决策过程 (Planning by Dynamic Programming) - 强化学习系列 贝叶斯优化 (Bayesian Optimization) 马尔可夫决策过程 (Markov Decision Process) - 强化学习系列 多臂赌博机 (Multi-armed Bandit) - 强化学习系列 强化学习简介 (Introduction of Reinforcement Learning) - 强化学习系列 在群晖 NAS 上编译安装 tmux 隐马尔可夫,条件随机场和序列标注 (Hidden Markov Model, Conditional Random Fields and Sequence Labeling) 图嵌入和图神经网络 (Graph Embedding and Graph Neural Network) 预训练自然语言模型 (Pre-trained Models for NLP) toB 产品用户权限 (User Privileges of toB Products) 京东数科 HIPO 学习之旅 (JDD HIPO Learning Journey) 杭州和东京之旅 (Tour of Hangzhou and Tokyo) 国际智慧温室种植挑战赛 (International Autonomous Greenhouse Challenge) 记忆中的儿时 (My Childhood in Memory) 启发式算法 (Heuristic Algorithms) 关不掉的浏览器标签页 (Browser Tabs You do not Close) 贝塞尔曲线 (Bézier Curve) 如何阅读一本书 (How to Read a Book) 相似性和距离度量 (Similarity and Distance Measurement) 集成学习算法 (Ensemble Learning) 计算复杂性与动态规划 (Computational Complexity and Dynamic Programming) 利用 Flask 和 Google App Engine 部署模型服务 序列到序列和注意力机制 (Seq2Seq and Attention Machanism) 词向量 (Word Embeddings) 循环神经网络 (Recurrent Neural Network, RNN) 泰国之行 (Tour of Thailand) 媒介之战 (War of Medias) 卷积神经网络 (Convolutional Neural Network, CNN) 买书,囤书,看书 (Buy Books, Hoard Books and Read Books) Play Safe, Smart Choice & Yuppie 基于 PyQt5/PySide2 和 QML 的跨平台 GUI 程序开发 流形学习 (Manifold Learning) 深度学习优化算法 (Optimization Methods for Deep Learning) 深度学习优化算法 (Optimization Methods for Deeplearning) 生成对抗网络简介 (GAN Introduction) Ising 模型,Hopfield 网络和受限的玻尔兹曼机 (Ising, Hopfield and RBM) 马尔科夫链蒙特卡洛方法和吉布斯采样 (MCMC and Gibbs Sampling) 特征值分解,奇异值分解和主成分分析 (EVD, SVD and PCA) 墨尔本之行 (Trip to Melbourne)
数据可视化小贴士 - 面向动态文档生成,秉承规范、统一和实用的理念
范叶亮 · 2024-01-07 · via 中文博客 on 范叶亮 | Leo Van

数据可视化小贴士

面向动态文档生成,秉承规范、统一和实用的理念

分类: 编程, 设计 / 字数: 3608 / 标签: 可视化, 一画胜千言, 设计规范, 可视化规范, Ant Vision, AntV, ECharts, Plotly, D3, Matplotlib, seaborn, plotnine, ggplot2, quarto, Jupyter Widgets, htmlwidgets, 布局, 色板, 字体, 尺寸, 响应式


文本主要面向不同格式文档(HTML、PDF、Word)的动态生成,秉承规范、统一和实用的理念总结数据可视化过程中的相关问题,不过度涉及数据可视化本身细节。

一画胜千言(A picture is worth a thousand words)是我个人很推崇的一个指引,不过前提是这得是一张「好图」,否则容易过犹不及。

一画胜千言

数据可视化是一门复杂的学问,在动态文档生成中,秉承规范、统一和实用的理念,我认为是快速提高数据可视化质量的不错之选。

设计规范

在之前的文章「设计语言初探」中探讨过产品的设计语言,在此针对各大企业的数据可视化规范并结合中文文档生成和个人偏好做简要分析。各大企业的数据可视化规范如下:

企业 数据可视化规范
Apple Human Interface Guidelines - Charts
Google Material Design - Data Visualization
Microsoft Data visualization style guidelines for Office Add-ins
Adobe Spectrum - Data Visualization
IBM Carbon Design System - Data Visualization
Salesforce Lightning Design System - Data Visualization
蚂蚁金服 Ant Vision

各家的设计理念有所不同,但我相信其目标是一致的,就是让用户可以更好更快地理解数据并从数据中获取洞见。上面的大多数数据可视化规范依旧是以面向产品设计为主,不过我认为大部分理念是可以迁移到文档中的可视化,尤其是 HTML 格式的动态文档。

Apple、Google、Microsoft 三大家的规范在自家系统的平台上针对简单的可视化场景可以说是最适用的,毕竟原生设计毫无违和感。但针对复杂的可视化场景,三家并没有给出更细的指引,不过也能理解针对商业数据可视化和科技绘图等复杂场景,确实更适合由上层(例如:库、应用等)去根据实际情况作出相应规范。

所以,站在规范统一的视角,我个人更倾向于选择适合中国宝宝体质的 Ant Vision。给出些我认为靠谱的理由:

  1. 设计体系基于具有更悠久历史的 Ant Design 衍生,具有完善的设计规范指引。
  2. 针对简单场景(例如:统计图表等)和复杂场景(例如:地图、关系图表等)都有较好的覆盖。
  3. 科学的色彩体系,在萝卜青菜各有所爱的配色之上给到了科学的指引。
  4. 最后也是我认为最重要的特点,开源,且有丰富的中文文档。

从规范和统一的角度,可以说 Ant Vision 是最优选择,有关 Ant Vision 的更多资料除了官网以外,还可以参见语雀上的 AntV 文档

工具选择

由于是面向动态文档生成为主,基于各种可视化工具的绘图很难嵌入自动化流水线中,因此本节主要讨论相关扩展包,不涉及专用的可视化工具(例如:Tableau,Power BI 等)。常用的可视化扩展包及其支持的语言和图类型,如下表所示:

扩展包 JS/TS Python R 统计图 地图 关系图
Ant Vision ⛔️ 1
ECharts ☑️ 2 ☑️ 3
Plotly
D3 ☑️ 4 5 ☑️ 6
Matplotlib
seaborn
plotnine
ggplot2

上述扩展包是我个人在实际项目中真实会使用到的,此时此刻就不难发现 Ant Vision 最大的问题就是对科学编程几乎 7 没有官方支持。

用于可视化的扩展包远不止上述的这 8 种,但我们不可能去学习使用所有的扩展包,这样于自己需要投入大量的学习成本,于团队也不利于项目的维护。即便就这 8 种扩展包,其语法也大不相同。

我接触的第一门绘图语言应该是 Logo,不过 Logo 是一门教学语言,所以在科学编程中使用的最早的是 Matlab 的绘图功能,Matplotlib 从名称上就不难看出是源自 Matlab。不过个人而言不是很喜欢 Matplotlib 的 API 风格,或者说我认为其 API 更偏底层一些。谈到这里就不得不谈一下「The Grammar of Graphics」,这也是我个人认为绘图「最舒服」的 ggplot2 扩展包背后的理论。在上述扩展包中,ggplot2 算是先驱者,plotnine 是 ggplot2 的 Python 复刻,Plotly 的 R 绑定可以支持直接将 ggplot2 对象绘制成 plotly 绘图,Ant Vision 则在该核心理论的基础上做了更多探索。所以当掌握了图形语法的理论基础后,对这些包的学习就相对会简单不少。由于长尾需求还是会存在,所以掌握不同可视化包的使用就成了技多不压身,我认为上述 8 种扩展包覆盖 99% 的可视化需求应该不成问题。

上述 8 种可视化包中,前 4 种都是以 JS/TS 库为基础,部分由官方或三方实现了 Python 和 R 的绑定,所以前 4 种天然就支持可交互绘图。利用 Python 的 Jupyter Widgets 和 R 的 htmlwidgets 实现在网页和 Notebook 中的可交互绘图。D3 背后的 Observable JS 也被当下流行的动态文档生成工具 quarto支持。后 4 种则只能创建不可交互的静态绘图,Matplotlib 作为 Python 绘图的重要可视化扩展包提供了丰富的绘图 API,seaborn 和 plotnine 均基于其开发,seaborn 简化了 API,plotnine 提供了 ggplot2 语法支持,而 ggplot2 则是 R 语言中数据可视化的不二之选。

讲了这么多并不是要在各个扩展包之间分个孰优孰劣,而是需要其特性和需求场景选择合适的扩展包。在此个人愚见如下:

  1. 动态绘图:Plotly > ECharts > D3 > Ant Vision,理由:多语言支持优先。
  2. 动态绘图(复杂场景,例如:地图、关系图等):Ant Vision > D3 > ECharts > Plotly,理由:交互性能优先。
  3. 静态绘图:ggplot2 = plotnine > seaborn > Matplotlib,理由:语法简单易于理解优先。
  4. 静态绘图(长尾需求,例如:示意图等)Matplotlib,理由:较为底层的绘图 API,使用更为灵活。

实用建议

根据规范,为了保证利用不同的工具绘图的视觉效果一致,我们需要在布局、色板、字体等多个角度进行自定义配置。下表展示了扩展包在不用语言绑定中样式的可自定义特性:

扩展包 JS/TS Python R
Ant Vision ☑️ 详情 - -
ECharts ☑️ 详情 ☑️ 详情 ☑️ 详情
Plotly ☑️ 详情 详情 ☑️ 详情,✅ 复用 ggplot2
D3 详情
Matplotlib - 详情 -
seaborn - ✅ 复用 Matplotlib -
plotnine - 详情 -
ggplot2 - - 详情

其中,✅ 表示支持自定义样式,且支持修改全局默认样式;☑️ 表示支持自定义样式,不支持修改全局默认样式,但支持通过函数一次性设置自定义样式;❌ 表示支持自定义样式,但需要每次手动配置所有样式细节。

布局

在 Ant Vision 设计语言中一个图应该包含标题、轴、图形、标签、注解、提示信息、图例等信息,如下图所示:

布局

大多数扩展包支持绝大多数元素,但对于一些相对特殊的元素(例如:注解,尤其是富文本的注解)支持较为有限。同时不同扩展包对于相同元素的样式控制也存在差异,这就导致很难将在不同扩展包之间做到完全统一,只能是尽可能相似。

色板

色板(配色)是影响统一的另一大重要因素,相比布局其更好做到不同扩展包之间的统一。根据 Ant Vision 的设计语言,色板分为:分类、顺序、发散、叠加、强调、语义共 6 大色板,如下图所示:

色板

不同扩展包不一定能覆盖所有类型色板(视其绘图能力而定)。除了选择合适的统一色板之外,不同类型色板在使用时也有各自的注意事项,虽然这无关样式统一,但却会从很大程度上影响数据可视化的效果。

字体

根据 Ant Vision 的设计语言,数据可视化字体应当具备三个条件:数字等宽、识别度高、混排美观,如下图所示:

字体

针对文档生成,个人总结了能够覆盖大部分文档场景且商用免费的字体,如下表所示:

字体名称 字体分类 语言 版权 建议使用场景
思源黑体 无衬线黑体 中英文 SIL开源,商用免费 网页正文
思源宋体 衬线宋体 中英文 SIL开源,商用免费 PDF&Word正文
方正仿宋 仿宋 中英文 商用免费 公文
方正楷体 楷体 中英文 商用免费 注释
ETbb 衬线 英文 MIT开源,商用免费 PDF&Word正文
Latin Modern Math TeX数学字体 英文 GFL开源,商用免费 数学公式
更纱黑体 等宽黑体 中英文 SIL开源,商用免费 代码

为了满足 Ant Vision 对字体的要求,在 Word 和 PDF 格式文档中的静态绘图可以使用更纱黑体。针对 HTML 格式文档,由于不会内嵌字体,为了适配不同的操作系统同时考虑不同字体的可用性,可以将交互式绘图字体设置为多个值:

{
  font-family: Iosevka, 'Iosevka Nerd', Consolas, 'Lucida Console', Menlo, Monaco, 'Andale Mono', 'Ubuntu Mono', 'Source Han Mono SC', 'Source Han Mono TC', 'Source Han Mono', 'Noto Sans Mono SC', 'Noto Sans Mono TC', 'Noto Sans Mono', monospace, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol' !important;
}

尺寸 & 响应式

错误的尺寸选择或不良的元素位置摆放都会导致可视化效果变差。PDF 和 Word 格式文档,以及 PC 端的 HTML 格式文档,通过限制页面宽度,可以相对统一的规范到标准的可读内容宽度。此时图片的最大宽度是已知的,可视化时仅需要考虑合适的宽高比即可。

针对移动端的 HTML 文档,由于可读内容宽度较小,绘图的尺寸则需要有针对性地进行调整。此时,使用交互式绘图则比静态绘图有更有优势,利用交互式绘图本身的响应式能力,可以减少人工调整的工作量,也更容易实现一套绘图代码处处可用的效果。

在动态文档生成过程中,我们很难预估数据的真实场景,一些极端情况往往可能会导致可视化结果完全不可用。因此在编写绘图代码时应充分考虑到数据类别的数量、数据类别名称的长度、数据分布等多种因素,同时将绘图中的不同元素摆放在合适的位置。编写出适应性更好的绘图代码才能保证动态文档的高可用性,当然这个过程不是一蹴而就的,随着真实数据中极端情况的积累,绘图代码也会越来越完善越来越鲁棒。