一、什么是 pyecharts?

pyecharts 是一款基于 Python 的强大可视化库,它无缝对接 ECharts,让开发者无需深入学习 JavaScript,就能用 Python 代码生成交互式图表 —— 从折线图、柱状图到地理地图、3D 模型,覆盖近百种可视化场景。尤其在地理数据展示上,pyecharts 的地图模块支持中国省市县多级区划,能轻松实现数据与地理区域的绑定,是统计分析、政务汇报、学术研究中展示地域数据的热门工具。无论是人口分布、GDP 差异还是疫情数据,都能通过它转化为直观的地图可视化成果。

二、pyecharts 的 “先天不足”:颜值与定制化的短板

尽管功能强大,pyecharts 的 “原生状态” 却常被诟病。一方面,默认样式过于朴素:地图底色单调、省份边界模糊、颜色渐变生硬,与专业设计工具产出的可视化作品相比,显得简陋粗糙;另一方面,定制化门槛暗藏玄机 —— 虽然提供了大量配置项,但参数分散、逻辑复杂,新手很容易陷入 “改了这处乱了那处” 的困境。比如想调整地图悬停效果,可能要同时修改itemstyle、tooltip、emphasis等多个配置,稍不注意就会导致图表错乱。这些问题让不少人觉得:“pyecharts 能画出来,但画不漂亮。”

三、调参,才是解锁 pyecharts 潜力的关键

事实上,pyecharts 的 “颜值天花板” 远未被默认配置限制。它的核心魅力恰恰在于高度可定制的参数体系 —— 就像给相机调光圈、快门能拍出不同风格的照片,修改 pyecharts 的配置项,能让同一份数据呈现出完全不同的视觉效果。比如通过bg_color更换地图背景为深邃星空蓝,用range_color设置渐变色带增强层次感,调整label_opts让省份名称既清晰又不突兀,再加上emphasis_opts配置悬停时的高亮动画…… 只需十几行参数调整,原本朴素的地图就能蜕变为符合大屏展示、汇报演讲的 “高颜值作品”。所谓 “工欲善其事,必先利其器”,掌握调参技巧,才能让 pyecharts 从 “能用” 变成 “好用、好看”。

如果我们平常用pyecharts实现地图数据可视化,是不是会得到以下的图表,这个图的确可以表达出数据分析的含义,但却没法拿的出手。

想做出精美的媲美大屏风格的地图可视化,需要对pyecharts进行全面剖析,比如对全局配置项、系列配置项,对其里面的各项参数,甚至包括内置的js代码,老规矩,先上代码,再上图,注释都在代码里:

from pyecharts.charts import Map
from pyecharts import options as opts
from pyecharts.commons.utils import JsCode

# 示例数据
province_data = [
    ("广东省", 126012510),
    ("山东省", 101527453),
    ("河南省", 99365519),
    ("四川省", 83674866),
    ("江苏省", 84748016),
    ("河北省", 74610235),
    ("湖南省", 66444864),
    ("浙江省", 64567588),
    ("安徽省", 61027171),
    ("湖北省", 57752557),
    ("广西壮族自治区", 50126804),
    ("云南省", 47209277),
    ("江西省", 45188635),
    ("辽宁省", 42591407),
    ("福建省", 41540086),
    ("陕西省", 39528999),
    ("黑龙江省", 31850088),
    ("山西省", 34915616),
    ("贵州省", 38562148),
    ("重庆市", 32054159),
    ("吉林省", 24073453),
    ("甘肃省", 25019831),
    ("内蒙古自治区", 24000207),
    ("上海市", 24870895),
    ("新疆维吾尔自治区", 25890094),
    ("北京市", 21893095),
    ("天津市", 13866009),
    ("海南省", 10081232),
    ("宁夏回族自治区", 7202654),
    ("青海省", 5923957),
    ("西藏自治区", 3648100)
]
gdp_data = [
    ("广东省", 124369.67), ("山东省", 83095.90), ("河南省", 58887.41),
    ("四川省", 53850.79), ("江苏省", 116364.2), ("河北省", 40391.3)
]

# 中国式大屏风格地图
china_map = (
    # InitOpts:初始化配置项
    Map(init_opts=opts.InitOpts(
        chart_id="123",
        bg_color="#001529",  # 深蓝色背景,符合政务大屏风格
        page_title="中国人口分布大屏",
    ))
   .add(
        series_name="人口数量",
        data_pair=province_data,
        maptype="china",
        zoom=1.2,  # 适当缩放,让地图居中显示
        center=[105, 36],  # 中国地理中心坐标
        itemstyle_opts=opts.ItemStyleOpts(
            area_color="#142957",  # 省份底色
            border_color="#00f2fe",  # 边界颜色,亮青色
            border_width=0.5,
            # opacity=0.5,
        )
    )
    .add(
        series_name="GDP",
        data_pair=gdp_data,
        maptype="china",
        zoom=1.2,  # 适当缩放,让地图居中显示
        center=[105, 36],  # 中国地理中心坐标
        itemstyle_opts=opts.ItemStyleOpts(
            area_color="#142957",  # 省份底色
            border_color="#00f2fe",  # 边界颜色,亮青色
            border_width=0.5,
            # opacity=0.5,
        )
    )
    # set_series_opts 系列配置项设置
   .set_series_opts(
        # label_opts 标签配置项
        label_opts=opts.LabelOpts(
            is_show=True,  # 是否显示标签
            color="#ffffff",  # 文字颜色
            font_size=8, # 文字字体大小
            font_weight="normal", # 文字字体粗细
            font_family="SimHei"# 文字字体系列
        ),
        # emphasis_opts 鼠标悬停效果
        emphasis_opts=opts.ItemStyleOpts(
            area_color="#00f2fe",  # 悬停时省份颜色
            border_color="#ffffff", # 图形描边颜色
            border_width=2, # 描边宽度
        )
    )
    # set_global_opts 全局配置项设置
   .set_global_opts(
        # title_opts 标题样式
        title_opts=opts.TitleOpts(
            title="中国各省份人口分布",
            subtitle="数据来源:最新人口普查数据",
            # title_textstyle_opts 主标题设置
            title_textstyle_opts=opts.TextStyleOpts(
                color="#00f2fe",  # 标题颜色
                font_size=36,
                font_weight="bold",
                font_family="SimHei"
            ),
            # subtitle_textstyle_opts 副标题设置
            subtitle_textstyle_opts=opts.TextStyleOpts(
                color="#ffffff",
                font_size=16,
            ),
            pos_top="2%",
            pos_left="center",
        ),
        # visualmap_opts 视觉映射配置
        visualmap_opts=opts.VisualMapOpts(
            is_show=True,
            type_="color",
            min_=3000000,
            max_=130000000,
            range_text=["高", "低"],
            range_color=["#00f2fe", "#0066b2", "#001529"],  # 蓝青色渐变,符合中国风
            textstyle_opts=opts.TextStyleOpts(color="#ffffff", font_size=10),
            pos_right="5%",
            pos_bottom="10%",
            item_width=15,
            item_height=100,
            border_color="#00f2fe",
            border_width=2
        ),
        # legend_opts 图例设置
        legend_opts=opts.LegendOpts(
            is_show=False
        ),
        # tooltip_opts 提示框样式
        tooltip_opts=opts.TooltipOpts(
            trigger="item",
            background_color="rgba(0, 21, 41, 0.9)",
            border_color="#00f2fe",
            border_width=1,
            textstyle_opts=opts.TextStyleOpts(color="#ffffff", font_size=16),
            formatter=JsCode("""
                function(params) {
                    return `<div style="padding:10px;">
                        <div style="font-size:12px;font-weight:bold;">${params.name}</div>
                        <div style="font-size:12px;margin-top:5px;">人口数量:${params.value.toLocaleString()}人</div>
                    </div>`;
                }
            """)
        )
    )    # 简化JS交互

)

china_map.render("china_population_big_screen.html")

我们可以看一下本次地图可视化呈现的效果了。

对于多指标切换怎么办?原本想按照正常图表中实现指标切换,但对pyecharts的JS代码调了一整天,这个VisualMapOpts:视觉映射配置项一直不能跟随指标上下限进行实时调整,无奈放弃了,只能换一个思路,做成tab方式,其实这个案例还可以继续优化其组件,让其更像大屏风格。

from pyecharts.charts import Map, Tab
from pyecharts import options as opts

# 示例数据
data_gdp = [("广东省", 10000), ("四川省", 20000), ("黑龙江省", 25000)]
data_population = [("广东省", 8000), ("四川省", 2300), ("黑龙江省", 2500)]

# 创建地图图表
map_gdp = Map(init_opts=opts.InitOpts(
        chart_id="gdp",
        bg_color="#001529",  # 深蓝色背景,符合政务大屏风格
        width = "900px",
        height = "500px",
        page_title="中国GDP分布大屏",
    ))
map_gdp.add("GDP", data_gdp, "china")
map_gdp.set_global_opts(
    title_opts=opts.TitleOpts(title="中国各省份GDP"),
    visualmap_opts=opts.VisualMapOpts(max_=30000)
)

map_population = Map(init_opts=opts.InitOpts(
        chart_id="population",
        bg_color="#001529",  # 深蓝色背景,符合政务大屏风格
        width = "900px",
        height = "500px",
        page_title="中国人口分布大屏",
    ))
map_population.add("Population", data_population, "china")
map_population.set_global_opts(
    title_opts=opts.TitleOpts(title="中国各省份人口"),
    visualmap_opts=opts.VisualMapOpts(max_=8000)
)

# 使用 Tab 创建切换界面
tab = Tab()
tab.add(map_gdp, "GDP")
tab.add(map_population, "Population")

# 渲染图表到 HTML 文件
tab.render("map_tabs.html")

tab切换的地图指标

关于随时间序列变化的数据,在pyecharts的示例中是有的,不过我们不需要那么复杂的,在此做了精简,完全可以参照之前的方式对地图再进行美化,这里就不再赘述了。

import pyecharts.options as opts
from pyecharts.globals import ThemeType
from pyecharts.commons.utils import JsCode
from pyecharts.charts import Timeline, Grid, Bar, Map, Pie

"""
Gallery 使用 pyecharts 1.0.0
参考地址: https://gallery.echartsjs.com/editor.html?c=xSkGI6zLmb

目前无法实现的功能:

1、
"""

data = [
    {
        "time": 1980,
        "data": [
            {"name": "台湾省", "value": [633.76, 12.28, "台湾省"]},
            {"name": "香港特别行政区", "value": [432.47, 8.38, "香港特别行政区"]},
            {"name": "江苏省", "value": [319.8, 6.2, "江苏省"]},
            {"name": "上海市", "value": [311.89, 6.05, "上海市"]},
            {"name": "山东省", "value": [292.13, 5.66, "山东省"]},
            {"name": "辽宁省", "value": [281, 5.45, "辽宁省"]},
            {"name": "广东省", "value": [249.65, 4.84, "广东省"]},
            {"name": "四川省", "value": [229.31, 4.44, "四川省"]},
            {"name": "河南省", "value": [229.16, 4.44, "河南省"]},
            {"name": "黑龙江省", "value": [221, 4.28, "黑龙江省"]},
        ],
    },
    {
        "time": 2000,
        "data": [
            {"name": "台湾省", "value": [27435.15, 19.47, "台湾省"]},
            {"name": "香港特别行政区", "value": [14201.59, 10.08, "香港特别行政区"]},
            {"name": "广东省", "value": [10741.25, 7.62, "广东省"]},
            {"name": "江苏省", "value": [8553.69, 6.07, "江苏省"]},
            {"name": "山东省", "value": [8337.47, 5.92, "山东省"]},
            {"name": "浙江省", "value": [6141.03, 4.36, "浙江省"]},
            {"name": "河南省", "value": [5052.99, 3.59, "河南省"]},
            {"name": "河北省", "value": [5043.96, 3.58, "河北省"]},
            {"name": "上海市", "value": [4771.17, 3.39, "上海市"]},
            {"name": "辽宁省", "value": [4669.1, 3.31, "辽宁省"]},
        ],
    },
    {
        "time": 2005,
        "data": [
            {"name": "台湾省", "value": [30792.89, 12.52, "台湾省"]},
            {"name": "广东省", "value": [22527.37, 9.16, "广东省"]},
            {"name": "江苏省", "value": [18598.69, 7.56, "江苏省"]},
            {"name": "山东省", "value": [18366.87, 7.47, "山东省"]},
            {"name": "香港特别行政区", "value": [14869.68, 6.05, "香港特别行政区"]},
            {"name": "浙江省", "value": [13417.68, 5.46, "浙江省"]},
            {"name": "河南省", "value": [10587.42, 4.3, "河南省"]},
            {"name": "河北省", "value": [10043.42, 4.08, "河北省"]},
            {"name": "上海市", "value": [9247.66, 3.76, "上海市"]},
            {"name": "辽宁省", "value": [8047.3, 3.27, "辽宁省"]},
        ],
    },
    {
        "time": 2010,
        "data": [
            {"name": "广东省", "value": [46036.25, 9.49, "广东省"]},
            {"name": "江苏省", "value": [41425.48, 8.54, "江苏省"]},
            {"name": "山东省", "value": [39169.92, 8.08, "山东省"]},
            {"name": "台湾省", "value": [30205.64, 6.23, "台湾省"]},
            {"name": "浙江省", "value": [27747.65, 5.72, "浙江省"]},
            {"name": "河南省", "value": [23092.36, 4.76, "河南省"]},
            {"name": "河北省", "value": [20394.26, 4.21, "河北省"]},
            {"name": "辽宁省", "value": [18457.3, 3.81, "辽宁省"]},
            {"name": "四川省", "value": [17185.48, 3.54, "四川省"]},
            {"name": "上海市", "value": [17165.98, 3.54, "上海市"]},
        ],
    },
    {
        "time": 2015,
        "data": [
            {"name": "广东省", "value": [72812.55, 9.35, "广东省"]},
            {"name": "江苏省", "value": [70116.38, 9, "江苏省"]},
            {"name": "山东省", "value": [63002.3, 8.09, "山东省"]},
            {"name": "浙江省", "value": [42886, 5.51, "浙江省"]},
            {"name": "河南省", "value": [37010.25, 4.75, "河南省"]},
            {"name": "台湾省", "value": [32604.52, 4.19, "台湾省"]},
            {"name": "四川省", "value": [30103.1, 3.87, "四川省"]},
            {"name": "河北省", "value": [29806.1, 3.83, "河北省"]},
            {"name": "湖北省", "value": [29550.19, 3.8, "湖北省"]},
            {"name": "湖南省", "value": [29047.2, 3.73, "湖南省"]},
        ],
    },
]


def get_year_chart(year: int):
    map_data = [
        [[x["name"], x["value"]] for x in d["data"]] for d in data if d["time"] == year
    ][0]
    print(year,'\n',map_data)
    min_data, max_data = (
        min([d[1][0] for d in map_data]),
        max([d[1][0] for d in map_data]),
    )
    map_chart = (
        Map()
        .add(
            series_name="",
            data_pair=map_data,
            label_opts=opts.LabelOpts(is_show=False),
            is_map_symbol_show=False,
            itemstyle_opts={
                "normal": {"areaColor": "#323c48", "borderColor": "#404a59"},
                "emphasis": {
                    "label": {"show": Timeline},
                    "areaColor": "rgba(255,255,255, 0.5)",
                },
            },
        )
        .set_global_opts(
            title_opts=opts.TitleOpts(
                title="1980年以来中国各省GDP排名变化情况",
                subtitle="GDP单位:亿元",
                pos_left="center",
                pos_top="top",
                title_textstyle_opts=opts.TextStyleOpts(
                    font_size=25, color="rgba(255,255,255, 0.9)"
                ),
            ),
            tooltip_opts=opts.TooltipOpts(
                is_show=True,
                formatter=JsCode(
                    """function(params) {
                    if ('value' in params.data) {
                        return params.data.value[2] + ': ' + params.data.value[0];
                    }
                }"""
                ),
            ),
            visualmap_opts=opts.VisualMapOpts(
                is_calculable=True,
                dimension=0,
                pos_left="10",
                pos_top="center",
                range_text=["High", "Low"],
                range_color=["lightskyblue", "yellow", "orangered"],
                textstyle_opts=opts.TextStyleOpts(color="#ddd"),
                min_=min_data,
                max_=max_data,
            ),
        )
    )
    return map_chart

# Draw Timeline
time_list = [1980, 2000, 2005, 2010, 2015]
timeline = Timeline(
    init_opts=opts.InitOpts(width="1200px", height="800px", theme=ThemeType.DARK)
)
for y in time_list:
    g = get_year_chart(year=y)
    timeline.add(g, time_point=str(y))

timeline.add_schema(
    orient="vertical",
    is_auto_play=True,
    is_inverse=True,
    play_interval=5000,
    pos_left="null",
    pos_right="5",
    pos_top="20",
    pos_bottom="20",
    width="50",
    label_opts=opts.LabelOpts(is_show=True, color="#fff"),
)

timeline.render("china_gdp_from_1980.html")

基于timeline的地图指标变化。

最后欢迎关注公众号:python与大数据分析

图片

Logo

永洪科技,致力于打造全球领先的数据技术厂商,具备从数据应用方案咨询、BI、AIGC智能分析、数字孪生、数据资产、数据治理、数据实施的端到端大数据价值服务能力。

更多推荐