Binning polar values with Julia


I have to bin periodic data. I was wondering if there are packages that can deal with polar binning in Julia. I have not been able to find it online.

Any help is appreciated!

Thank you in advance!

Can you give an example of your data?

Would rose plots qualify as “polar binning”?

The CircStats.jl package and this reference seem relevant.

A rose plot would be what I need but I only need the data separated into bins, not the plot itself.

@danrib07, you may have a look at code here.

I’m not certain your use case, but this is simple enough:

using Distributions

# assume a and b are in radians
# compute intrinsic distance on the circle. Works for any interval.
function circdist(a, b)
    d = a - b
    return (d ≈ π ? -one(d) * π : rem(d, oftype(d, 2) * π, RoundNearest))

# simulate data in [-3π/4, 5π/4]
pts = rand(VonMises(π / 4, 10), 1000)

edges = range(-π, π; length=20)
midpoints = (edges[1:end-1] .+ edges[2:end]) ./ 2

bins = map(pts) do p
    argmax([circdist(m, p) for m in midpoints])

If you want to fit a histogram, it’s probably a good idea to center your data around 0 first. You can do this for example using Manifolds

using Manifolds, StatsBase
M = Circle()
μ = mean(M, pts)  # intrinsic mean, approximately π / 4,
pts_centered = log.(Ref(M), μ, pts)  # data with intrinsic mean of 0
hist_centered = fit(Histogram, pts_centered)
edges_centered = only(hist_centered.edges)
midpoints_centered = (edges_centered[1:end-1] .+ edges_centered[2:end]) ./ 2
bins = map(pts_centered) do p
    argmax(distance.(Ref(M), midpoints_centered, p))
# get the uncentered midpoints of the bins
midpoints = exp.(Ref(M), μ, midpoints_centered)
1 Like

@sethaxen, could you please elaborate a bit on the use of manifolds here?

Also, in circdist() what is the need for one() and oftype(), as the multiplication by π seems to always produce floats?


Fyi, the circular distance function was written more compactly in the links provided as: cdist(a, b) = mod(b - a + π, 2π) - π

1 Like

Sure, here we create the real Circle manifold, where points are represented as angles in radians over some interval. The call to mean computes the intrinsic (i.e. Riemannian mean), which generalizes the usual mean to nonlinear spaces and respects the periodicity of the data. log computes the Riemannian logarithm map from the mean to each point. You don’t need to know what this means, but the geometric idea is that it rotates the circle (and the data) so that the mean is at the 0 angle and then flattens it (by unwinding) into an interval of [-π, π], thus centering the data on 0. This can all be done with addition/subtraction and mod, but I do it this way because I can never remember the appropriate mod, and these functions work for any manifold.
The rest of the code just now ignores the circle and works with our interval. At the end, we use exp (the opposite of log), to undo the centering and get back bin midpoints that can be directly compared to our data.

These are just there for type stability. Otherwise depending on the values, a Float or an Irrational might be returned. The code you gave looks simpler and type-stable and probably does the same thing.

1 Like