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

Julia中如何为Makie散点图添加自定义图例?

在CairoMakie中为散点图添加自定义标签图例

问题背景

已有如下数据与初始绘图代码:

using DataFrames, CairoMakie, RDatasets

iris_df = dataset("datasets", "iris")[:, 1:4];
preds = rand((0, 1), 150)

# 初始散点图
p = scatter(
  iris_df[:, 2], iris_df[:, 3],
  color=preds,
  dpi=300,
)

尝试添加图例时多次触发MethodError,以下是两种失败尝试及对应报错:

尝试1:直接传入FigureAxisPlot对象

Legend(p, ["label2", "label1"])

报错信息:

ERROR: MethodError: no method matching _block(::Type{Legend}, ::Makie.FigureAxisPlot, ::Vector{String})
Closest candidates are:
  _block(::Type{<:Makie.Block}, ::Union{GridPosition, GridSubposition}, ::Any...; kwargs...) at C:\Users\Shayan\.julia\packages\Makie\Ggejq\src\makielayout\blocks.jl:287
  _block(::Type{<:Makie.Block}, ::Union{Figure, Scene}, ::Any...; bbox, kwargs...) at C:\Users\Shayan\.julia\packages\Makie\Ggejq\src\makielayout\blocks.jl:298

尝试2:传入Scatter对象

f = Figure()
Axis(f[1, 1])

p = scatter!(
  iris_df[:, 2], iris_df[:, 3],
  color=preds,
  dpi=300,
)

Legend(p, ["label2", "label1"])

报错信息:

ERROR: MethodError: no method matching _block(::Type{Legend}, ::Scatter{Tuple{Vector{Point{2, Float32}}}}, ::Vector{String})
Closest candidates are:
  _block(::Type{<:Makie.Block}, ::Union{GridPosition, GridSubposition}, ::Any...; kwargs...) at C:\Users\Shayan\.julia\packages\Makie\Ggejq\src\makielayout\blocks.jl:287
  _block(::Type{<:Makie.Block}, ::Union{Figure, Scene}, ::Any...; bbox, kwargs...) at C:\Users\Shayan\.julia\packages\Makie\Ggejq\src\makielayout\blocks.jl:298

解决方案

CairoMakie的Legend需要先指定在Figure中的放置位置,再关联对应颜色类别与标签,以下是两种可行实现方式:

方式1:手动创建图例项匹配颜色映射

using DataFrames, CairoMakie, RDatasets

iris_df = dataset("datasets", "iris")[:, 1:4];
preds = rand((0, 1), 150)

# 创建Figure和Axis
f = Figure()
ax = Axis(f[1, 1], xlabel="SepalWidth", ylabel="PetalLength")

# 绘制散点图
scatter!(ax, iris_df[:,2], iris_df[:,3], color=preds, dpi=300)

# 在Figure右侧位置创建图例,匹配颜色与自定义标签
Legend(f[1,2], 
       [MarkerElement(color=c) for c in Makie.current_default_theme().palette.color[]], 
       ["label0", "label1"], 
       title="Preds")

display(f)

方式2:分组绘制自动生成图例

将数据按preds分组后分别绘制,Makie会自动识别图例项:

using DataFrames, CairoMakie, RDatasets

iris_df = dataset("datasets", "iris")[:, 1:4];
preds = rand((0, 1), 150)
# 合并数据以便分组
df = hcat(iris_df, DataFrame(preds=preds))

f = Figure()
ax = Axis(f[1,1], xlabel="SepalWidth", ylabel="PetalLength")

# 按preds分组绘制,每组指定标签
for (label, sub_df) in pairs(groupby(df, :preds))
    scatter!(ax, sub_df.SepalWidth, sub_df.PetalLength, label="label$(label.preds)", dpi=300)
end

# 自动生成图例并指定位置
axislegend(ax, position=:right)

display(f)

错误原因说明

之前的报错是因为Legend构造函数必须先指定其在Figure中的网格位置(如f[1,2]),而非直接传入绘图对象。必须明确图例的放置区域,再关联对应的绘图元素或标签。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 17:10:16