查看全课大纲(第 27 / 45 节)

矩形树图

矩形树图:可视化层级数据的占比关系

小象实战讲义 · ECharts 数据可视化

在上一节学习了饼图之后,你是否想过,当数据本身具有层级结构时,如何同时展示其层级关系和各个部分的占比呢?矩形树图(Treemap)正是为此而生。本节我们将学习矩形树图的原理、适用场景,并掌握如何使用 pyecharts 构建一个交互式的矩形树图,让你能够清晰地洞察具有从属关系的数据中各成分的比例。

💡 核心导读

  • 图表定位:矩形树图是一种用于展示层级结构数据,并能直观体现同级节点间数值占比的可视化图表。
  • 核心原理:通过嵌套的矩形来表示父子节点的从属关系,矩形的面积大小通常对应节点的数值大小。
  • 数据格式:构建矩形树图的关键在于将数据组织成树形结构的列表,每个节点是一个包含 name、value 和 children 等属性的字典。
  • 交互优势:pyecharts 实现的矩形树图支持点击缩放和下钻导航,便于用户探索多层级的细节数据。
  • 选型对比:与仅展示从属关系的树形图不同,矩形树图强调占比;但当子节点占比过小时,文本标签可能难以排布。

一、认识矩形树图:从磁盘空间到数据洞察

矩形树图由 Ben Shneiderman 教授在上世纪90年代提出,最初是为了有效了解磁盘空间的使用情况。它将一个树状结构的数据,映射到一个平面的矩形空间里。

  • 层级与占比:它不仅能展示数据间的从属关系(父子节点),还能通过矩形面积的大小,直观地比较同级节点之间的数值占比。这弥补了普通树形图只能展示结构,无法展示数量的不足。
  • 空间利用:相比传统的树形图,矩形树图能更高效地利用空间,将所有节点信息在一个矩形区域内铺开,像一张数据地图,引导我们探索和发现。
  • 交互探索:在 ECharts/pyecharts 中,矩形树图支持丰富的交互。你可以通过点击矩形块进行缩放聚焦,也可以通过底部的“面包屑导航”栏层层深入或返回,实现交互式的数据探索。

下图展示了一个简单的矩形树图结构示意:

┌─────────────────────────────────────────────┐
│                   根节点                     │
├───────────────┬─────────────────────────────┤
│   类别A       │           类别B             │
│   (面积小)    │          (面积大)           │
│               ├─────┬─────┬─────┬─────┤    │
│               │子类A│子类B│子类C│子类D│    │
│               │     │     │     │     │    │
└───────────────┴─────┴─────┴─────┴─────┴────┘

优点与局限:

  • 优点:空间利用率高,能同时展示层级关系和数值占比。
  • 局限:当某个分类的数值占比过小时,对应的矩形区域会非常小,导致其中的文本标签难以清晰显示和排布。

如何选择:

  • 如果仅需展示数据的层级或从属关系,使用树形图即可。
  • 如果既要展示从属关系,又要比较各部分的占比大小,那么矩形树图是更合适的选择。

二、构建树形结构数据

和绘制树形图一样,使用 pyecharts 绘制矩形树图的难点和关键点在于数据格式的构造。我们必须将数据组织成特定的树形结构(嵌套的字典列表),才能被 TreeMap 组件正确解析。

这种结构是一个列表,列表中的每个元素代表一个节点,通常是一个字典。字典中常用的键包括:

  • name: 节点的名称。
  • value: 节点的数值,它决定了该节点(及其子节点所占整体)的矩形面积。
  • children: 一个列表,用于存放该节点的子节点。如果节点没有子节点(即叶子节点),则可以省略此键。

让我们通过一个具体的例子来理解。假设我们有以下层级数据:

  • 根节点下有两个主要类别:类别A(值为40)和 类别B(值为180)。
  • 类别B 下有一个子节点 类别B的children(值为76)。
  • 类别B的children 下又有四个子类:子类A(12)、子类B(28)、子类C(20)、子类D(16)。

在 Python 中,我们这样构造数据:

from pyecharts import options as opts
from pyecharts.charts import TreeMap

treemap_data = [
    {
        "value": 40,
        "name": "类别A"
    },
    {
        "value": 180,
        "name": "类别B",
        "children": [
            {
                "value": 76,
                "name": "类别B的children",
                "children": [
                    {"value": 12, "name": "类别B的子类A"},
                    {"value": 28, "name": "类别B的子类B"},
                    {"value": 20, "name": "类别B的子类C"},
                    {"value": 16, "name": "类别B的子类D"},
                ]
            }
        ]
    }
]

treemap_chart = (
    TreeMap(init_opts=opts.InitOpts(width="800px", height="600px"))
    .add(
        series_name="所有数据",  # 系列名称
        data=treemap_data,      # 传入树形结构数据
        # 可以设置矩形标签、颜色等视觉选项
        label_opts=opts.LabelOpts(position="inside", font_size=12),
        levels=[
            opts.TreeMapLevelsOpts(
                treemap_itemstyle_opts=opts.TreeMapItemStyleOpts(
                    border_color="#555", border_width=1, gap_width=2
                )
            )
        ]
    )
    .set_global_opts(
        title_opts=opts.TitleOpts(title="矩形树图示例"),
        toolbox_opts=opts.ToolboxOpts(),
    )
)

treemap_chart.render_embed()
print(f"图表类型: {type(treemap_chart).__name__}")
print(f"顶级节点数量: {len(treemap_data)}")
print(f"第一层名称: {[item['name'] for item in treemap_data]}")
print(f"类别B的子节点数量: {len(treemap_data[1]['children'][0]['children'])}")
图表类型: TreeMap
顶级节点数量: 2
第一层名称: ['类别A', '类别B']
类别B的子节点数量: 4
矩形树图,不同大小的矩形色块表示销售额占比
图:矩形树图:用矩形面积表示销售额占比,面积越大占比越高,嵌套层级表达两级分类。手机端可左右滑动查看,点击图片可看全图。

在这个结构中:

  • 类别A 和 类别B 是并列的同级节点,属于根节点下的第一层。
  • 由于 类别B 的 value (180) 远大于 类别A 的 value (40),在图中 类别B 的矩形面积将大约是 类别A 的4.5倍。
  • 类别B 拥有 children,所以它是一个父节点,其面积由其子节点 类别B的children 的数值(76)决定,并进一步细分给四个孙节点。

三、使用 pyecharts 绘制矩形树图

数据准备好后,调用 TreeMap 类绘制图表就非常直观了。上面这个完整块把“构造树形数据”和“绘制并验证图表”放在一起,单独运行即可复现。

代码解析:

  1. TreeMap(): 初始化一个矩形树图实例。
  2. .add(): 添加数据系列。series_name 是系列名称,会显示在提示框和图例中;data 就是我们构造的树形数据。
  3. levels: 用于配置不同层级的样式。TreeMapLevelsOpts 可以设置每一层矩形的边框、间隙等。
  4. set_global_opts(): 设置全局配置,如图表标题、工具箱等。

上述代码已经完成图表构建并通过 render_embed() 生成内嵌 HTML。将它放入 Notebook 或网页后,浏览器中会显示一个交互式矩形树图:

  • 面积对比:左侧 类别B 的矩形面积明显大于右侧 类别A。
  • 层级嵌套:类别B 的矩形内部被分割成了四个更小的矩形,分别对应其四个子类。
  • 交互操作:
    • 鼠标滚轮:在图上滚动可以缩放视图。
    • 点击矩形:点击任意矩形(如 类别B),视图会平滑过渡并聚焦到该矩形,将其置于中心位置。
    • 面包屑导航:图表下方会出现一个导航栏(如 所有数据 > 类别B > 类别B的children),点击其中任意层级,视图会快速跳转到对应层级,方便你层层下钻或返回上级。

四、从理论到实践:理解数据与图形的映射

现在,让我们结合生成的数据和图表,加深理解:

  1. 数值与面积的映射:类别A 的 value 是40,类别B 的 value 是180。在图中,类别B 的面积大约是 类别A 的4.5倍(180/40),这与视觉感受一致。
  2. 子节点数值的继承:类别B 的 value 是180,但这个数值并不直接决定其内部四个子类矩形的总面积。实际上,类别B 内部区域的总面积由它的直接子节点 类别B的children 的 value (76) 来代表,并在此区域内按子类A-D的数值(12, 28, 20, 16)进行二次划分。value 为180更多是用于与 类别A 进行顶级比较。
  3. 交互的价值:当数据层级较多时,初始视图可能无法看清底层细节。通过点击下钻,可以聚焦到特定分支进行深入分析,这是静态图片无法提供的动态探索体验。

📝 动手练一练

  1. 数据改造:尝试修改 treemap_data 中 类别B的子类B 的 value,将其从28改为56。重新运行绘图代码,观察图表中该子类对应的矩形面积发生了怎样的变化?它与其他子类的面积比例关系是否符合你的预期?
点击查看参考答案

修改数据部分如下:

treemap_data = [
    # ... 类别A部分不变 ...
    {
        "value": 180,
        "name": "类别B",
        "children": [
            {
                "value": 76,
                "name": "类别B的children",
                "children": [
                    {"value": 12, "name": "类别B的子类A"},
                    {"value": 56, "name": "类别B的子类B"}, # 修改此处
                    {"value": 20, "name": "类别B的子类C"},
                    {"value": 16, "name": "类别B的子类D"},
                ]
            }
        ]
    }
]

观察结果:类别B的子类B 的矩形面积会显著增大。在 类别B的children 内部,四个子类的数值总和变为 12+56+20+16=104。子类B 的新占比为 56/104 ≈ 53.8%,其面积将超过其他三个子类的面积之和,成为该区域中最大的部分。这直观地反映了数值变化对占比和视觉面积的影响。

  1. 场景思考:假设你需要向管理层汇报公司全年各产品线的营收构成,而每个产品线下又有不同的细分型号。你认为使用矩形树图是否合适?为什么?如果某个明星产品型号的营收占比极高,而其他多个长尾型号占比极低,使用矩形树图可能会遇到什么问题?
点击查看参考答案

是否合适:非常合适。公司营收数据天然具有层级结构(公司→产品线→型号),矩形树图既能展示这种从属关系,又能通过矩形面积清晰对比不同产品线乃至不同型号之间的营收占比,一目了然地看出哪些是营收主力。

可能遇到的问题:如果存在“明星型号”和大量“长尾型号”,即数据分布极不均衡时,矩形树图的局限性就会显现:

  • 标签重叠与不可读:占比极低的长尾型号对应的矩形会非常小,无法容纳下型号名称的文本标签,导致这些区域在图上成为“无名”的色块,信息缺失。
  • 视觉焦点分散:大量微小的矩形可能使图表看起来杂乱,反而干扰了对主要组成部分(明星型号)的观察。

应对建议:在这种情况下,可以考虑:

  • 数据聚合:将营收占比低于某个阈值(如1%)的所有长尾型号合并为一个“其他”类别。
  • 分层展示:先展示产品线层级,点击某个产品线后再下钻查看其内部型号详情,避免一次性展示过多细节。
  • 结合其他图表:用一张柱状图展示前10大型号的营收,用另一张饼图或矩形树图展示产品线层级的占比。

本章小结

本节我们深入学习了矩形树图,一种强大的、用于可视化层级数据及其占比关系的工具。你不仅理解了它的设计原理和适用场景,更重要的是,掌握了使用 pyecharts 将树形结构的数据转化为交互式图表的具体方法。

📋 行动清单

  • 理解核心:明确矩形树图的核心价值是在展示层级关系的同时,通过面积表达占比,并能与纯展示结构的树形图进行区分。
  • 掌握数据构造:能够根据业务数据,熟练地构造出符合 pyecharts TreeMap 要求的、嵌套的树形字典列表结构。
  • 实践交互探索:在生成的矩形树图中,尝试使用点击、滚轮缩放和面包屑导航,体验交互式数据下钻与上卷的过程,理解其在复杂数据分析中的优势。

—— 小象教研组