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
相关产品推荐
相关产品推荐

