You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python散点图如何将默认标记替换为自定义SVG天气图标?

错误原因

你使用parse_path返回的是第三方svg解析库(通常为svgpathtools)的Path对象,不属于Matplotlib原生支持的marker参数格式,且该自定义对象不可哈希,无法被Matplotlib内部缓存机制调用,因此抛出不可哈希类型报错。

解决方案

方案1:转换为Matplotlib原生Path作为自定义marker

需要先将SVG路径解析为Matplotlib支持的matplotlib.path.Path对象,同时对路径坐标做归一化处理,避免标记尺寸异常:

import matplotlib.pyplot as plt
from matplotlib.path import Path
import numpy as np
# 引入专门的转换库替代原svgpathtools的parse_path
from svgpath2mpl import parse_path

# 你的SVG路径字符串
svg_path_str = """M 350.04,161.95
C 350.04,161.95 391.76,120.24 391.76,120.24M 120.24,391.76
C 120.24,391.76 161.96,350.04 161.96,350.04M 389.00,256.00
C 389.00,256.00 448.00,256.00 448.00,256.00M 64.00,256.00
C 64.00,256.00 123.00,256.00 123.00,256.00M 350.04,350.04
C 350.04,350.04 391.76,391.76 391.76,391.76M 120.24,120.24
C 120.24,120.24 161.96,161.95 161.96,161.95M 256.00,389.00
C 256.00,389.00 256.00,447.99 256.00,447.99M 256.00,64.00
C 256.00,64.00 256.00,123.00 256.00,123.00M 157.56,216.68M 150.90,242.12
C 150.31,246.60 150.00,251.26 150.00,256.00
150.00,256.01 150.00,256.02 150.00,256.02
150.00,314.57 197.46,362.02 256.00,362.02
314.54,362.02 362.00,314.57 362.00,256.02
362.00,197.48 314.54,150.02 256.00,150.02
220.35,150.02 188.80,167.63 169.59,194.62M 276.00,170.00
C 217.46,170.00 170.01,217.46 170.01,276.00
170.01,300.17 178.09,322.45 191.71,340.28
209.54,353.90 231.82,361.99 255.99,361.99
314.53,361.99 361.99,314.53 361.99,255.99
361.99,231.83 353.90,209.55 340.29,191.72
322.52,178.10 300.28,170.00 276.16,170.00
276.11,170.00 276.05,170.00 276.00,170.00
276.00,170.00 276.00,170.00 276.00,170.00 Z"""

clear_marker = parse_path(svg_path_str)
# 坐标归一化,将路径缩放到(-1,1)区间适配marker尺寸
clear_marker.vertices -= clear_marker.vertices.mean(axis=0)
max_extent = np.max(np.abs(clear_marker.vertices))
clear_marker.vertices /= max_extent

# 测试绘图
x = np.random.rand(10)
y = np.random.rand(10)
plt.plot(x, y, marker=clear_marker, linestyle='', markersize=20)
plt.show()

注:使用该方案需要先安装svgpath2mpl库,可直接完成SVG路径到Matplotlib Path的转换,避免手动解析的繁琐。


方案2:直接加载SVG文件作为标记(更适合多天气图标场景)

如果你有多个不同的天气SVG图标,更推荐使用AnnotationBbox直接将SVG作为图像贴到散点位置,适配性更高,不需要处理路径转换逻辑:

import io
import matplotlib.pyplot as plt
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
import cairosvg
from PIL import Image
import numpy as np

# SVG转可用图像的工具函数
def svg_to_image(svg_path, size=30):
    png_data = cairosvg.svg2png(url=svg_path, output_width=size, output_height=size)
    return Image.open(io.BytesIO(png_data))

# 示例:加载晴天图标,给对应天气的点加标记
sun_icon = svg_to_image("sun.svg", size=40)
imagebox = OffsetImage(sun_icon, zoom=1)

x = np.random.rand(10)
y = np.random.rand(10)
fig, ax = plt.subplots()
ax.scatter(x, y, alpha=0) # 先绘制透明散点占位
# 给每个点添加对应天气图标
for xi, yi in zip(x, y):
    ab = AnnotationBbox(imagebox, (xi, yi), frameon=False)
    ax.add_artist(ab)
plt.show()

注:使用该方案需要先安装cairosvg、pillow库完成SVG到图像的转换。


内容的提问来源于stack exchange,提问作者Somnus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 08:54:05