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

地理坐标系Geo

地理坐标系 Geo:从热力图到航线图

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

在上一节中,我们学习了如何使用 Map 组件绘制基础的地图。本节我们将深入 Geo 地理坐标系组件。如果说 Map 是绘制单一区域数值的“标准地图”,那么 Geo 则是一个功能更强大的“地理画布”。它不仅支持多种数据标记样式(如散点、热力、涟漪、航线),还能在同一张地图上叠加多种视觉元素,为展示复杂的地理空间关系提供了可能。学完本节,你将能利用 Geo 绘制热力分布图、分段统计图以及动态的航线迁徙图。

💡 核心导读

  • Geo vs Map:Geo 是一个地理坐标系,支持在其上绘制多种图表类型(scatter, effectScatter, heatmap, lines),而 Map 主要用于展示区域填充地图。
  • 四种核心图表类型:掌握 Geo 中 type_ 参数的四种取值,分别对应散点图、涟漪散点图、热力图和航线图。
  • 分段视觉映射:通过 VisualMapOpts(is_piecewise=True) 将连续的颜色映射转换为分段区间,便于进行等级划分。
  • 航线图绘制:理解航线数据 (source, target) 的结构,并学会使用 EffectOpts 和 LineStyleOpts 美化航线。
  • 官方文档查阅:学会如何通过查阅 pyecharts 源码和官方文档,确认可用的配置项与枚举值。

一、认识地理坐标系 Geo

Geo 组件在 pyecharts 中代表一个地理坐标系。你可以把它想象成一张空白的、带有经纬度网格的地图底板。与 Map 组件直接绘制区域颜色不同,Geo 的核心功能是在这个底板上“添加”各种地理数据点或连线。

关键区别:

  • Map:主要用于展示区域本身的数值,通过颜色深浅(视觉映射)来区分不同区域的值,如各省份的GDP。
  • Geo:主要用于展示地理坐标点上的信息或点与点之间的关系。例如,城市空气质量监测点(散点)、人口密度分布(热力)、航班线路(航线)。

使用 Geo 的第一步是使用 .add_schema() 方法设定地图底板。

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

# 1. 创建Geo实例
geo = Geo()

# 2. 添加地理坐标系,设定地图类型为中国
geo.add_schema(maptype="china")

# 3. 此时已有一个空白中国地图底板,可以继续添加数据
print(f"已创建 {type(geo).__name__} 实例,并设定了中国地图底板。")
已创建 Geo 实例,并设定了中国地图底板。

二、绘制热力地图 (Heatmap)

热力地图用于直观展示地理区域内数据的密度或强度分布。在 Geo 中,通过设置 type_=ChartType.HEATMAP 来实现。

数据格式:与 Map 类似,是一个由 [(区域名, 数值), ...] 组成的列表。Geo 会根据区域名找到对应的坐标,并根据数值大小在该坐标周围渲染出渐变的热力效果。

from pyecharts.charts import Geo
from pyecharts import options as opts
from pyecharts.globals import ChartType

# 模拟各省份数据
data = [
    ("广东省", 150),
    ("北京市", 95),
    ("上海市", 120),
    ("浙江省", 80),
    ("江苏省", 110),
    ("四川省", 65),
    ("湖北省", 70),
    ("陕西省", 55),
]

# 创建图表
heatmap = (
    Geo()
    .add_schema(maptype="china")
    .add(
        series_name="业务热度",  # 系列名称
        data_pair=data,         # 数据
        type_=ChartType.HEATMAP, # 指定为热力图类型
    )
    .set_global_opts(
        title_opts=opts.TitleOpts(title="全国业务热度分布(热力图)"),
        visualmap_opts=opts.VisualMapOpts(max_=150), # 视觉映射,最大值对应颜色最深
    )
)

# 生成HTML(在讲义中不打印完整HTML,仅作验证)
html_content = heatmap.render_embed()
print(f"热力地图HTML生成成功,包含 {len(html_content)} 个字符。")
print(f"数据系列: '业务热度',包含 {len(data)} 个省份的数据点。")
中国地图上的业务热度热力图,城市位置呈高亮色块
图:全国业务热度分布热力图:颜色越亮表示业务量越集中,省会城市自然形成高亮区域。手机端可左右滑动查看,点击图片可看全图。
热力地图HTML生成成功,包含 6039 个字符。
数据系列: '业务热度',包含 8 个省份的数据点。

效果解读:地图上会出现从浅色到深色的渐变圆形区域,颜色越深表示该省份的“业务热度”值越高。你可以通过拖拽视觉映射组件(visualMap)来动态筛选显示特定数值范围的数据。

三、绘制分段型地图

有时,我们希望将连续的数据划分为几个明确的等级区间(如优、良、中、差),并用不同的颜色块表示。这需要用到分段型视觉映射。

核心配置:在 VisualMapOpts 中设置 is_piecewise=True。pyecharts 会自动根据数据范围生成等距分段。你也可以通过 pieces 参数自定义分段区间和颜色。

下面的例子使用涟漪散点图 (EFFECT_SCATTER) 来展示点数据,并结合分段视觉映射。

from pyecharts.charts import Geo
from pyecharts import options as opts
from pyecharts.globals import ChartType

# 使用与热力图相同的数据,便于对比
data = [
    ("广东省", 150),
    ("北京市", 95),
    ("上海市", 120),
    ("浙江省", 80),
    ("江苏省", 110),
    ("四川省", 65),
    ("湖北省", 70),
    ("陕西省", 55),
]

piecewise_map = (
    Geo()
    .add_schema(maptype="china")
    .add(
        "质量等级",
        data,
        type_=ChartType.EFFECT_SCATTER, # 使用涟漪散点图
    )
    .set_series_opts(label_opts=opts.LabelOpts(is_show=False)) # 关闭点标签
    .set_global_opts(
        title_opts=opts.TitleOpts(title="数据质量等级分布(分段图)"),
        visualmap_opts=opts.VisualMapOpts(
            is_piecewise=True,  # 开启分段
            max_=150,
            # 可以在此处自定义 pieces,这里使用自动分段
        ),
    )
)

html_content = piecewise_map.render_embed()
print(f"分段型地图HTML生成成功,包含 {len(html_content)} 个字符。")
print(f"视觉映射类型: 'piecewise' (分段),数据被自动分为若干区间。")
分段型地图HTML生成成功,包含 6411 个字符。
视觉映射类型: 'piecewise' (分段),数据被自动分为若干区间。

交互效果:生成的地图旁会有一个分段图例,点击不同的色块,地图上会高亮显示处于该数值区间的省份点,其他点会变淡,非常适合进行分层筛选分析。

四、绘制航线图 (Lines)

航线图用于展示地理点之间的流动关系,如航班线路、人口迁徙、货物运输等。

核心概念:

  • 数据格式:每条航线是一个元组 (source, target),表示从 source 地点到 target 地点。
  • 叠加绘制:通常先用地标点 (EFFECT_SCATTER) 标出重要城市,再用线 (LINES) 连接它们。
  • 美化配置:
    • EffectOpts: 用于设置航线的动画效果,如箭头符号、颜色、大小。
    • LineStyleOpts: 用于设置航线样式,如曲线程度 (curve)、颜色、宽度。
from pyecharts.charts import Geo
from pyecharts import options as opts
from pyecharts.globals import ChartType, SymbolType

# 1. 定义城市坐标点(这里用名称,Geo会自动查找内置坐标)
city_data = [("广州市", 100), ("北京市", 90), ("上海市", 95), ("杭州市", 85), ("重庆市", 80)]

# 2. 定义航线数据:从广州飞往其他城市
flight_route = [
    ("广州市", "上海市"),
    ("广州市", "北京市"),
    ("广州市", "杭州市"),
    ("广州市", "重庆市"),
]

# 3. 绘制图表
flight_map = (
    Geo()
    .add_schema(maptype="china")
    # 添加城市点(白色涟漪点)
    .add(
        series_name="城市",
        data_pair=city_data,
        type_=ChartType.EFFECT_SCATTER,
        color="white",
        symbol_size=8,
    )
    # 添加航线
    .add(
        series_name="航班",
        data_pair=flight_route,
        type_=ChartType.LINES,
        # 航线特效:蓝色箭头
        effect_opts=opts.EffectOpts(
            symbol=SymbolType.ARROW,
            symbol_size=6,
            color="blue"
        ),
        # 航线样式:轻微弯曲的实线
        linestyle_opts=opts.LineStyleOpts(curve=0.2, width=2, opacity=0.7),
    )
    .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
    .set_global_opts(title_opts=opts.TitleOpts(title="广州出发主要航线图"))
)

html_content = flight_map.render_embed()
print(f"航线图HTML生成成功,包含 {len(html_content)} 个字符。")
print(f"包含 {len(city_data)} 个城市点,{len(flight_route)} 条航线。")
print(f"航线特效: 箭头符号,曲线参数 curve=0.2。")
航线图HTML生成成功,包含 8050 个字符。
包含 5 个城市点,4 条航线。
航线特效: 箭头符号,曲线参数 curve=0.2。

图表解读:地图上“广州市”位置会有一个白色涟漪点,从它发出四条带蓝色箭头的曲线,分别指向上海、北京、杭州和重庆。箭头方向指示了流向,曲线使图表更美观且避免线路重叠。

📝 动手练一练

  1. 自定义热力图数据:请将以下某日全国部分城市PM2.5指数数据绘制成热力图。
    pm25_data = [("北京市", 145), ("石家庄市", 188), ("郑州市", 162), ("西安市", 132), ("成都市", 98), ("武汉市", 115), ("上海市", 75), ("广州市", 45)]
    <details>
    <summary> 点击查看参考答案</summary>

    ```python
    from pyecharts.charts import Geo
    from pyecharts import options as opts
    from pyecharts.globals import ChartType

    pm25_data = [("北京市", 145), ("石家庄市", 188), ("郑州市", 162), ("西安市", 132), ("成都市", 98), ("武汉市", 115), ("上海市", 75), ("广州市", 45)]

    chart = (
        Geo()
        .add_schema(maptype="china")
        .add("PM2.5指数", pm25_data, type_=ChartType.HEATMAP)
        .set_global_opts(
            title_opts=opts.TitleOpts(title="部分城市PM2.5指数热力图"),
            visualmap_opts=opts.VisualMapOpts(max_=200)
        )
    )
    # 验证生成
    print(f"图表 '{type(chart).__name__}' 创建成功。")
    print(f"使用了 {len(pm25_data)} 个城市的数据。")
```text

图表 ‘Geo’ 创建成功。 使用了 8 个城市的数据。 ```

  1. 升级航线图:修改航线图示例,增加一条从“上海市”到“重庆市”的航线,并将这条航线的颜色设置为红色 (color="red"),曲线程度改为 0.5。

    点击查看参考答案
    from pyecharts.charts import Geo
    from pyecharts import options as opts
    from pyecharts.globals import ChartType, SymbolType
    
    city_data = [("广州市", 100), ("北京市", 90), ("上海市", 95), ("杭州市", 85), ("重庆市", 80)]
    flight_route = [
        ("广州市", "上海市"),
        ("广州市", "北京市"),
        ("广州市", "杭州市"),
        ("广州市", "重庆市"),
    ]
    
    flight_chart = (
        Geo()
        .add_schema(maptype="china")
        .add("城市", city_data, type_=ChartType.EFFECT_SCATTER, color="white")
        .add(
            "航班",
            flight_route,
            type_=ChartType.LINES,
            effect_opts=opts.EffectOpts(symbol=SymbolType.ARROW, symbol_size=6, color="blue"),
            linestyle_opts=opts.LineStyleOpts(curve=0.2),
            # 注意:上述配置会对所有航线生效。要为单条航线单独设置样式,需要使用更高级的'set_series_opts'配合formatter,或拆分数据系列。
            # 此处为简化,我们新增一个专门针对上海-重庆航线的系列。
        )
        .set_global_opts(title_opts=opts.TitleOpts(title="升级版航线图"))
    )
    flight_chart.add(
        "新增航线",
        [("上海市", "重庆市")],
        type_=ChartType.LINES,
        effect_opts=opts.EffectOpts(symbol=SymbolType.ARROW, symbol_size=6, color="red"),
        linestyle_opts=opts.LineStyleOpts(curve=0.5, width=2, opacity=0.7),
    )
    
    print(f"航线图已升级,共包含 {len(flight_route)+1} 条航线。")
    print("其中,'上海市' -> '重庆市' 航线为红色,曲线更明显。")
```text
航线图已升级,共包含 5 条航线。
其中,'上海市' -> '重庆市' 航线为红色,曲线更明显。
*提示:在实际复杂场景中,需要对不同属性的航线进行分组时,将其拆分为多个 `.add()` 系列是更清晰的做法。*
</details>

本章小结

本节我们掌握了 pyecharts 中功能强大的 Geo 地理坐标系组件。它超越了 Map 的单一区域着色功能,为我们提供了在地理底板上绘制散点、热力、涟漪、航线等多种图表类型的能力。通过组合这些类型和视觉映射组件,我们可以生动地展现数据的空间分布、密度以及地理实体间的动态关系。

📋 行动清单

  • 动手实践:在本地环境中运行本节所有代码示例,并尝试修改数据、颜色、曲线参数等,观察图表变化。
  • 查阅文档:访问 pyecharts 官方文档,查看 GeoOpts、EffectOpts、LineStyleOpts 的完整参数列表,了解还有哪些美化选项。
  • 构思场景:思考你手头的数据(如销售网点、物流轨迹、用户分布)适合用 Geo 的哪种图表类型来呈现,并尝试设计一个简单的可视化方案。

—— 小象教研组