Has anyone made scatter plots with hexagonal binning?

Something came up in my research where I’m doing a scatter plot with way too many points.

Has anyone had experience making hexagonally binned plots like the ones seen here:

// preferably with pgfplots (or plots.jl), but beggars can’t be choosers

1 Like

Doesn’t Plots.jl have a hexbin function?

3 Likes

Looks like it’s only supported for PyPlots, though.

https://github.com/JuliaPlots/Plots.jl/search?q=hexbin&type=Code

I started rolling my own hexbin plotting function. It’s not super fast, but it works:

36%20AM


  • cell 1
using GeometricalPredicates

xmin = -15
xmax = 30
ymin = -80
ymax = 170

num_hexagons = 25

dx = xmax - xmin
dy = ymax - ymin

aspect_ratio = (3/4) * dx/dy
width = ( xmax - xmin ) / num_hexagons

xx = [ -1/2 , 0 , 1/2 , 1/2 , 0 , -1/2 , -1/2 ] * width
yy = [ 1/4 , 1/2 , 1/4, -1/4, -1/2, -1/4 , 1/4 ] * width / aspect_ratio

cur_hexagons = Array{Any}(num_hexagons+1, num_hexagons+1)

for cur_row in 0:num_hexagons
    x_offset = isodd(cur_row) ? (dx/num_hexagons) / 2 : 0 
    for cur_col in 0:num_hexagons
        tmp_xx = xx - dx/2 - xmin/2 + dx/num_hexagons*cur_col + x_offset
        tmp_yy = yy - dy/2 - ymin/2 + dy/num_hexagons*cur_row
        
        cur_hexagons[cur_row+1, cur_col+1] = Polygon(map(cur_zip -> Point(cur_zip...), collect(zip(tmp_xx,tmp_yy))[1:end-1])...)
    end
end

  • cell 2
aa = linspace(xmin, xmax, 200)
bb = sin.(2*2*pi*aa/dx) * dy/2 + (dy/2 + ymin)

cur_info = Array{Any}(num_hexagons+1, num_hexagons+1)

cur_points = map(cur_zip -> Point(cur_zip...), collect(zip(aa,bb)))

for cur_row in 0:num_hexagons
    for cur_col in 0:num_hexagons
        cur_hexagon = cur_hexagons[cur_row+1, cur_col+1]
        cur_info[cur_row+1, cur_col+1] = count(cur_point -> inpolygon(cur_hexagon, cur_point), cur_points)
    end
end

  • cell 3
plot()
for cur_row in 0:num_hexagons
    for cur_col in 0:num_hexagons
        cur_hexagon = cur_hexagons[cur_row+1, cur_col+1]
        tmp_xx = map(cur_vertex -> cur_vertex._x, cur_hexagon._p)
        tmp_yy = map(cur_vertex -> cur_vertex._y, cur_hexagon._p)
        
        push!(tmp_xx, cur_hexagon._p[1]._x)
        push!(tmp_yy, cur_hexagon._p[1]._y)
        
        tmp_cc = cur_info[cur_row+1, cur_col+1]
        
        iszero(tmp_cc) && continue
        plot!(tmp_xx, tmp_yy,aspect_ratio=aspect_ratio, label="", fill=true, fillopacity=0.2, color=tmp_cc)
    end
end
# scatter!(aa,bb, label="")

xlims!(xmin, xmax)
ylims!(ymin, ymax)
3 Likes

Here’s something I put together a while back: GitHub - RalphAS/HexBinPlots.jl: hexbins for the rest of the Julians. It’s also rather slow, and last time I tried it didn’t work with the pgfplots backend, but it did what I wanted at the time.

It should definitely work with at least GR as well

1 Like

Can you provide an example of this?

// I get a backend not supported message (if I’m doing it the correct way?)

No I just now that GR has native hexbins. If it doesn’t works out of the box could you raise an issue?