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

其他相关性图表

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

在掌握了散点图、气泡图和热力图这些基础的数据关系可视化图表后,我们还需要一些更“特别”的图表来应对复杂的关系描述场景。本节将介绍三种功能独特的图表:特效散点图、桑基图和树状图。它们分别用于增强视觉吸引力、展示数据流动关系和呈现层级从属关系。学完本节,你将能够为你的数据分析结果选择并绘制更具表现力的关系型图表。

💡 核心导读

  • 特效散点图:在标准散点图基础上,为数据点添加动态涟漪效果,提升视觉吸引力和交互感。
  • 桑基图:一种流图,通过节点和带宽度链接直观展示数据在不同类别间的流向与流量大小。
  • 树状图:以树形结构可视化层级或从属关系,关键在于将数据组织成嵌套的 name 和 children 结构。

一、特效散点图:让散点“动”起来

特效散点图,在 ECharts 官网也称为涟漪散点图,其本质是散点图的一种样式拓展。它通过在数据点周围添加动态扩散的涟漪效果,使静态的图表更具视觉动感和吸引力,尤其适合在数据大屏或需要突出关键数据点的场景中使用。

在 pyecharts 中,我们使用 EffectScatter 类来创建特效散点图。其核心 API 与 Scatter 类似,但增加了一个 symbol 参数,允许我们自定义涟漪中心的图形标识。

# 导入必要的库
from pyecharts import options as opts
from pyecharts.charts import EffectScatter
from pyecharts.globals import SymbolType

# 准备数据
x_data = ["A", "B", "C", "D", "E"]
y_data = [10, 20, 15, 25, 18]

# 创建特效散点图
chart = (
    EffectScatter()
    .add_xaxis(xaxis_data=x_data)
    .add_yaxis(
        series_name="示例数据",
        y_axis=y_data,
        # 关键:指定涟漪中心的图形标识,这里使用箭头
        symbol=SymbolType.ARROW,
        # 可以调整涟漪效果的大小和周期
        effect_opts=opts.EffectOpts(scale=3, period=4),
    )
    .set_global_opts(
        title_opts=opts.TitleOpts(title="特效散点图(箭头标识)"),
        xaxis_opts=opts.AxisOpts(type_="category"),
        yaxis_opts=opts.AxisOpts(type_="value"),
    )
)

# 打印图表类型和系列数据摘要
print(f"图表类型: {type(chart).__name__}")
print(f"X轴数据: {x_data}")
print(f"Y轴数据: {y_data}")
print(f"使用的符号: {SymbolType.ARROW}")

印刷输出:

图表类型: EffectScatter
X轴数据: ['A', 'B', 'C', 'D', 'E']
Y轴数据: [10, 20, 15, 25, 18]
使用的符号: arrow

代码解读与配置要点:

  1. 核心类:使用 EffectScatter 替代 Scatter。
  2. 符号类型:通过 symbol 参数,我们可以使用 SymbolType 枚举类中的常量(如 ARROW, RECT, DIAMOND, TRIANGLE 等)来改变涟漪中心的图形。默认是圆形 (CIRCLE)。
  3. 涟漪效果:effect_opts 参数接收一个 EffectOpts 对象,可以控制涟漪的缩放比例 (scale) 和动画周期 (period),从而调整动态效果的强度与速度。
  4. 数据格式:其数据格式与普通散点图完全一致,支持数值型和类目型坐标轴。

二、桑基图:可视化数据流动

桑基图是一种特定类型的流图,用于描述一组值到另一组值的流向。它通过节点(矩形)和连接线(流)来呈现数据流动的路径,其中连接线的宽度与流动的数据量大小成正比。这种图表非常适合分析能源、资金、用户流量、物料等在多个环节间的转移与分布情况。

一个桑基图主要包含两个核心数据结构:

  • 节点 (Nodes):代表流程中的各个阶段或类别,是一个字典列表,每个字典通常包含 name 键。
  • 链接 (Links):定义节点之间的流动关系,也是一个字典列表,每个字典包含 source(源节点名)、target(目标节点名)和 value(流量值)三个关键键。
# 导入必要的库
from pyecharts import options as opts
from pyecharts.charts import Sankey

# 1. 准备节点数据
nodes = [
    {"name": "原料采购"},
    {"name": "生产制造"},
    {"name": "质检"},
    {"name": "仓储"},
    {"name": "线上销售"},
    {"name": "线下销售"},
]

# 2. 准备链接数据(定义流动关系)
links = [
    {"source": "原料采购", "target": "生产制造", "value": 100},
    {"source": "生产制造", "target": "质检", "value": 95},  # 假设有5%的损耗
    {"source": "质检", "target": "仓储", "value": 90},     # 假设5%不合格
    {"source": "仓储", "target": "线上销售", "value": 60},
    {"source": "仓储", "target": "线下销售", "value": 30},
]

# 3. 创建桑基图
chart = (
    Sankey()
    .add(
        series_name="产品流转",
        nodes=nodes,
        links=links,
        # 设置连接线的样式:透明度0.2,弯曲度0.5,颜色跟随源节点
        linestyle_opt=opts.LineStyleOpts(opacity=0.2, curve=0.5, color="source"),
        # 设置节点标签显示在右侧
        label_opts=opts.LabelOpts(position="right"),
        # 设置节点之间的距离
        node_gap=10,
    )
    .set_global_opts(title_opts=opts.TitleOpts(title="产品生产销售桑基图"))
)

# 打印数据摘要
print(f"节点数量: {len(nodes)}")
print(f"链接数量: {len(links)}")
print("链接示例(第一条):", links[0])
产品生产销售桑基图,节点之间的连线宽度表示数量大小
图:桑基图:产品从生产到销售的流量分配,分支宽度表示各环节的数量占比。手机端可左右滑动查看,点击图片可看全图。

印刷输出:

节点数量: 6
链接数量: 5
链接示例(第一条): {'source': '原料采购', 'target': '生产制造', 'value': 100}

代码解读与配置要点:

  1. 数据结构是核心:桑基图的绘制难点在于正确构造 nodes 和 links 数据。source 和 target 的值必须与 nodes 中某个字典的 name 值严格匹配。
  2. 样式配置:
    • linestyle_opt:控制连接线的样式。color=“source” 表示连接线的颜色与其源节点的颜色一致,这有助于追踪流动路径。
    • label_opts:控制节点标签的显示位置,“right” 是常用选项。
    • node_gap:可以调整节点之间的纵向间距,避免拥挤。
  3. 解读图表:生成的图表会清晰显示从“原料采购”流出的线最宽(100),随后在“生产制造”和“质检”环节宽度变窄,表示有损耗。最后在“仓储”节点后分流至“线上”和“线下”销售,宽度比例对应其 value 值(60 vs 30)。

三、树状图:呈现层级与从属关系

树状图用于可视化层级结构或从属关系,例如公司组织架构、文件目录、分类体系等。它从一个根节点开始,通过分叉展示父子关系,直到叶子节点(没有子节点的节点)。

在 pyecharts 中绘制树状图的关键,同样在于数据结构的组织。树形数据通常被表示为一个嵌套的字典列表结构,每个节点是一个字典,包含 name(节点名称)和可选的 children(子节点列表)字段。

# 导入必要的库
from pyecharts import options as opts
from pyecharts.charts import Tree

# 1. 构造树形结构数据
# 这是一个典型的嵌套结构,描述了A为根,B、C、D为子节点,C和D又有自己的子节点。
tree_data = [
    {
        "name": "总经理 (A)",
        "children": [
            {"name": "技术部 (B)"},
            {
                "name": "市场部 (C)",
                "children": [
                    {"name": "推广组 (E)"},
                    {"name": "品牌组 (F)"},
                ],
            },
            {
                "name": "销售部 (D)",
                "children": [
                    {"name": "华东区 (G)"},
                ],
            },
        ],
    }
]

# 2. 创建树状图(默认从左至右布局)
chart = (
    Tree()
    .add(
        series_name="组织架构",
        data=tree_data,
        # 初始树布局方向:LR(从左到右)、RL(从右到左)、TB(从上到下)、BT(从下到上)
        orient="LR",
        # 标签样式配置:右对齐、居中对齐、旋转-90度(适用于垂直布局时)
        label_opts=opts.LabelOpts(
            horizontal_align="right",
            vertical_align="middle",
            # rotate=-90, # 当orient为"TB"或"BT"时,可取消注释使标签垂直
        ),
        symbol_size=10, # 节点符号大小
    )
    .set_global_opts(title_opts=opts.TitleOpts(title="公司组织架构树状图"))
)

# 打印数据结构摘要
print("树状图数据根节点名称:", tree_data[0]["name"])
print("根节点的直接子节点数量:", len(tree_data[0]["children"]))
print("第一个子节点名称:", tree_data[0]["children"][0]["name"])
公司组织架构树状图,从总公司向下展开多个部门节点
图:树状图:公司组织架构的层级关系,父节点展开后可以看到下级部门。手机端可左右滑动查看,点击图片可看全图。

印刷输出:

树状图数据根节点名称: 总经理 (A)
根节点的直接子节点数量: 3
第一个子节点名称: 技术部 (B)

代码解读与配置要点:

  1. 数据构造:数据必须是一个列表,即使只有一个根节点。每个节点是字典,children 键对应的值是一个节点列表,以此实现无限嵌套。没有 children 键的节点即为叶子节点。
  2. 布局方向:orient 参数控制树的生长方向,可选 “LR”(左->右)、“RL”(右->左)、“TB”(上->下)、“BT”(下->上)。根据标签长度和层级深度选择合适的布局。
  3. 标签优化:当树垂直生长(TB/BT)时,较长的节点名可能导致标签重叠。可以通过 label_opts 中的 rotate(旋转)和 horizontal_align、vertical_align(对齐方式)来调整,改善可读性。
  4. 处理复杂数据:对于从外部 JSON 文件加载的复杂树形数据(如示例中的 flare.json),确保其结构符合上述规范。可以使用 json.load() 读取后,将得到的字典放入一个列表中作为 data 参数传入。

📝 动手练一练

  1. 改造散点图:将一段你自己用 pandas 生成的包含 [x, y] 坐标的 DataFrame 数据(至少5个点),用特效散点图画出来,并将点的符号改为三角形 (SymbolType.TRIANGLE)。
点击查看参考答案
import pandas as pd
from pyecharts.charts import EffectScatter
from pyecharts import options as opts
from pyecharts.globals import SymbolType

# 生成示例 DataFrame
df = pd.DataFrame({
    'x': [1, 2, 3, 4, 5],
    'y': [2, 4, 1, 5, 3]
})

chart = (
    EffectScatter()
    .add_xaxis(df['x'].tolist())
    .add_yaxis("我的数据", df['y'].tolist(), symbol=SymbolType.TRIANGLE)
    .set_global_opts(title_opts=opts.TitleOpts(title="我的特效散点图"))
)
print("使用三角形符号的特效散点图已创建。")
print(f"数据点数量: {len(df)}")
使用三角形符号的特效散点图已创建。
数据点数量: 5
  1. 设计简单桑基图:假设你有三个学习阶段:“预习”、“听课”、“练习”。设计一个桑基图,表示有100人开始预习,其中80人进入听课阶段,听课的人中有60人完成了练习。请写出对应的 nodes 和 links 数据。
点击查看参考答案
nodes = [
    {"name": "预习"},
    {"name": "听课"},
    {"name": "练习"},
]

links = [
    {"source": "预习", "target": "听课", "value": 80},
    {"source": "听课", "target": "练习", "value": 60},
]
# 注意:这里"预习"到"听课"的100人中只有80人流动,所以value是80。
# "听课"到"练习"的流动值是60。
print("节点:", nodes)
print("链接:", links)
节点: [{'name': '预习'}, {'name': '听课'}, {'name': '练习'}]
链接: [{'source': '预习', 'target': '听课', 'value': 80}, {'source': '听课', 'target': '练习', 'value': 60}]

本章小结

本章我们深入探讨了数据关系可视化的多种图表。从基础的散点图、气泡图到能够展示分布密度的热力图,再到本节具有特殊表现力的特效散点图、桑基图和树状图,你已经拥有了一个应对不同关系分析场景的“图表工具箱”。记住,选择哪种图表,永远取决于你想要讲述的数据故事和需要揭示的关系类型。

📋 行动清单

  • 尝试组合:在一个数据大屏的草稿中,思考哪些位置可以用桑基图展示流程,哪些地方用树状图展示结构。
  • 数据准备练习:找到一份具有层级关系的数据(如部门预算、产品分类),尝试将其整理成树状图所需的嵌套字典结构。
  • 样式调试:为桑基图调整不同的 linestyle_opt(如颜色、曲率)和 label_opts,观察其对图表可读性的影响。

—— 小象教研组

配套资料 · 直接下载

课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。

  • flare.json · ECharts 课程配套资源
    课程配套文件
    下载