hexbin

hexbin(xs, ys; kwargs...)              

Plots a heatmap with hexagonal bins for the observations xs and ys .

Attributes

Specific to Hexbin

  • bins = 20 : If an Int , sets the number of bins in x and y direction. If a Tuple{Int, Int} , sets the number of bins for x and y separately.

  • cellsize = nothing : If a Real , makes equally-sided hexagons with width cellsize . If a Tuple{Real, Real} specifies hexagon width and height separately.

  • threshold::Int = 1 : The minimal number of observations in the bin to be shown. If 0, all zero-count hexagons fitting into the data limits will be shown.

  • scale = identity : A function to scale the number of observations in a bin, eg. log10.

Generic

  • colormap::Union{Symbol, Vector{<:Colorant}} = :viridis

  • colorrange::Tuple(<:Real,<:Real} = Makie.automatic sets the values representing the start and end points of colormap .

Examples

Setting the number of bins

Setting bins to an integer sets the number of bins to this value for both x and y. The minimum number of bins in one dimension is 2.

using CairoMakie

using Random
Random.seed!(1234)

f = Figure(resolution = (800, 800))

x = rand(300)
y = rand(300)

for i in 2:5
    ax = Axis(f[fldmod1(i-1, 2)...], title = "bins = $i", aspect = DataAspect())
    hexbin!(ax, x, y, bins = i)
    wireframe!(ax, Rect2f(Point2f.(x, y)), color = :red)
    scatter!(ax, x, y, color = :red, markersize = 5)
end

f          

You can also pass a tuple of integers to control x and y separately.

using CairoMakie

using Random
Random.seed!(1234)

f = Figure(resolution = (800, 800))

x = rand(300)
y = rand(300)

for i in 2:5
    ax = Axis(f[fldmod1(i-1, 2)...], title = "bins = (3, $i)", aspect = DataAspect())
    hexbin!(ax, x, y, bins = (3, i))
    wireframe!(ax, Rect2f(Point2f.(x, y)), color = :red)
    scatter!(ax, x, y, color = :red, markersize = 5)
end

f          

Setting the size of cells

You can also control the cell size directly by setting the cellsize keyword. In this case, the bins setting is ignored.

The height of a hexagon is larger than its width. This is why setting the same size for x and y will result in uneven hexagons.

using CairoMakie

using Random
Random.seed!(1234)

f = Figure(resolution = (800, 800))

x = rand(300)
y = rand(300)

for (i, cellsize) in enumerate([0.1, 0.15, 0.2, 0.25])
    ax = Axis(f[fldmod1(i, 2)...], title = "cellsize = ($cellsize, $cellsize)", aspect = DataAspect())
    hexbin!(ax, x, y, cellsize = (cellsize, cellsize))
    wireframe!(ax, Rect2f(Point2f.(x, y)), color = :red)
    scatter!(ax, x, y, color = :red, markersize = 5)
end

f          

To get evenly sized hexagons, set the cell size to a single number. This number defines the cell width, the height will be computed as 2 * step_x / sqrt(3) . Note that the visual appearance of the hexagons will only be even if the x and y axis have the same scaling, which is why we use aspect = DataAspect() in these examples.

using CairoMakie

using Random
Random.seed!(1234)

f = Figure(resolution = (800, 800))

x = rand(300)
y = rand(300)

for (i, cellsize) in enumerate([0.1, 0.15, 0.2, 0.25])
    ax = Axis(f[fldmod1(i, 2)...], title = "cellsize = $cellsize", aspect = DataAspect())
    hexbin!(ax, x, y, cellsize = cellsize)
    wireframe!(ax, Rect2f(Point2f.(x, y)), color = :red)
    scatter!(ax, x, y, color = :red, markersize = 5)
end

f          

Hiding hexagons with low counts

All hexagons with a count lower than threshold will be removed:

using CairoMakie

using Random
Random.seed!(1234)

f = Figure(resolution = (800, 800))

x = randn(100000)
y = randn(100000)

for (i, threshold) in enumerate([1, 10, 100, 500])
    ax = Axis(f[fldmod1(i, 2)...], title = "threshold = $threshold", aspect = DataAspect())
    hexbin!(ax, x, y, cellsize = 0.4, threshold = threshold)
end
f          

Changing the scale of the number of observations in a bin

You can pass a scale function to via the scale keyword, which will be applied to the bin counts before plotting.

using CairoMakie

using Random
Random.seed!(1234)

x = randn(100000)
y = randn(100000)

f = Figure()
hexbin(f[1, 1], x, y, bins = 40,
    axis = (aspect = DataAspect(), title = "scale = identity"))
hexbin(f[1, 2], x, y, bins = 40, scale=log10,
    axis = (aspect = DataAspect(), title = "scale = log10"))
f          

Showing zero count hexagons

By setting threshold = 0 , all hexagons that fit into the limits of the input data are shown. In this example, we add a transparent color to the start of the colormap and stroke each hexagon so the empty hexagons are visible but not too distracting.

using CairoMakie

using DelimitedFiles


a = map(Point2f, eachrow(readdlm(assetpath("airportlocations.csv"))))

f, ax, hb = hexbin(a,
    cellsize = 6,
    axis = (; aspect = DataAspect()),
    threshold = 0,
    colormap = [Makie.to_color(:transparent); Makie.to_colormap(:viridis)],
    strokewidth = 0.5,
    strokecolor = :gray50,
    scale = Makie.pseudolog10)

tightlimits!(ax)

Colorbar(f[1, 2], hb,
    label = "Number of airports",
    ticks = (0:3, ["0", "10", "100", "1000"]),
    height = Relative(0.5)
)
f