Julia:网格上分类数据的可视化

Ant*_*rev 8 plot heatmap julia categorical-data

有时需要在规则网格上绘制分类值以显示它们如何覆盖某个区域。原则上,plot() 函数非常适合这种情况,但是有一个问题需要每次调整图标的大小以创建实体封面的错觉。更改图像的覆盖范围时,旧尺寸变得无关紧要,需要再次调整。有没有一种技术可以自动调整这个大小?

using Plots
using CategoricalArrays
a = [1, 2, 3, 1, 2, 3, 1, 2, 3]
b = [1, 1, 1, 2, 2, 2, 3, 3, 3]
c = CategoricalArray(["X", "X", "Y", "Z", "Y", "Y", "Z", "Y", "Z"])
plot(a, b, group = c, seriestype = :scatter, aspect_ratio = 1, markersize=90, 
markershape=:square, markerstrokewidth=0.0, xlim = (0.5, 3.5), ylim = (0.5, 3.5))
Run Code Online (Sandbox Code Playgroud)

结果在所有方面都很好,除了每次需要调整单元格的大小以使没有重叠区域或间隙时:

在此处输入图片说明

作为替代方案,我考虑了 heatmap(),但它对分类数据的工作非常奇怪,通过连续的值渐变为它们设置某种规模。我还没有遇到任何使用 heatmap() 会得到带有像 plot() 这样美丽图例的地图的例子,所以我不确定在这里使用 heatmap() 是否正确。

a = b = [1, 2, 3]
c = CategoricalArray(["X" "X" "Y"; "Z" "Y" "Y"; "Z" "Y" "Z"])
heatmap(a, b, c)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

也许还有一些方法可以自动设置plot()的单元格大小?

ahn*_*abb 5

在 Plots.jl 中创建此类绘图的方法有多种。也许对你想要的最明显的解释是形状。对于这种方法,您还需要了解如何将未连接的数据分组到同一组中。基于形状的解决方案可能如下所示:

\n
a = [1, 2, 3, 1, 2, 3, 1, 2, 3]\nb = [1, 1, 1, 2, 2, 2, 3, 3, 3]\nc = CategoricalArray(["X", "X", "Y", "Z", "Y", "Y", "Z", "Y", "Z"])\n\ngroups = Dict(cat => NTuple{2,Int}[] for cat in levels(c))\nfor (ca, cb, cat) in zip(a,b,c)\n    push!(groups[cat], (ca,cb))\nend\n\nw = 1\nshapes = map(collect(groups)) do (cat, vals)\n    cat => mapreduce(vcat, vals) do (ca, cb)\n        [ca cb] .+ [-.5 -.5; .5 -.5; .5 .5; -.5 .5; -.5 -.5; NaN NaN]*w\n    end\nend\n\np = plot(aspect_ratio=1)\nfor (cat, s) in sort(shapes;by=x->x[1])\n    plot!(s[:,1], s[:,2], label=cat, seriestype=:shape, linewidth=0)\nend\n
Run Code Online (Sandbox Code Playgroud)\n

在此输入图像描述

\n

大多数代码只是简单地移动数据,因此我们从分类值到指定所有顶点的矩阵得到一个对向量,就像“X”一样:

\n
"X" =>\n12\xc3\x972 Matrix{Float64}:\n   0.5    0.5\n   1.5    0.5\n   1.5    1.5\n   0.5    1.5\n   0.5    0.5\n NaN    NaN\n   1.5    0.5\n   2.5    0.5\n   2.5    1.5\n   1.5    1.5\n   1.5    0.5\n NaN    NaN\n
Run Code Online (Sandbox Code Playgroud)\n

一个可能稍微简单一点的解决方案是“欺骗”绘图以使用热图显示我们想要的内容,如下所示:

\n
a = b = [1, 2, 3]\nc = CategoricalArray(["X" "X" "Y"; "Z" "Y" "Y"; "Z" "Y" "Z"])\npal = palette(:default)\np = plot(aspect_ratio=1, size=(400,400))\nheatmap!(a,b,c, c=pal, colorbar=false, clims=(1,length(pal)))\nfor cat in sort(collect(Set(c)))\n    plot!(\n        [], [], seriestype=:shape,\n        label=cat, color=pal[levelcode(cat)]\n    )\nend\n
Run Code Online (Sandbox Code Playgroud)\n

在此输入图像描述

\n