# Binning polar values with Julia

**URL:** https://discourse.julialang.org/t/binning-polar-values-with-julia/62754
**Category:** Statistics
**Tags:** question
**Created:** [June 11, 2021, 4:52pm UTC](https://discourse.julialang.org/t/binning-polar-values-with-julia/62754 "2021-06-11T16:52:54Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![danrib07](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danrib07/32/212751_2.png) [@danrib07](https://discourse.julialang.org/u/danrib07)
#### Post date: [June 11, 2021, 4:52pm UTC](https://discourse.julialang.org/t/binning-polar-values-with-julia/62754/1 "2021-06-11T16:52:54Z")

</div>

Hello,

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!

---

<div class="post-metadata">

### Author: ![sethaxen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sethaxen/32/35604_2.png) [@sethaxen](https://discourse.julialang.org/u/sethaxen)
#### Post date: [June 11, 2021, 5:18pm UTC](https://discourse.julialang.org/t/binning-polar-values-with-julia/62754/2 "2021-06-11T17:18:02Z")

</div>

Can you give an example of your data?

---

<div class="post-metadata">

### Author: ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)
#### Post date: [June 11, 2021, 5:32pm UTC](https://discourse.julialang.org/t/binning-polar-values-with-julia/62754/3 "2021-06-11T17:32:27Z")

</div>

Would [rose plots](https://discourse.julialang.org/t/how-to-make-a-wind-rose-in-julia/40229/10) qualify as “polar binning”?

The [CircStats.jl](https://github.com/anowacki/CircStats.jl/blob/master/src/CircStats.jl) package and this [reference](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&ved=2ahUKEwinnc_lkpDxAhWQKewKHT9ZA_AQFjABegQIBBAD&url=https%3A%2F%2Fwww.jstatsoft.org%2Farticle%2Fview%2Fv031i10%2Fv31i10.pdf&usg=AOvVaw3WtvFXj1NCR99mzgXiD0cu) seem relevant.

---

<div class="post-metadata">

### Author: ![danrib07](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danrib07/32/212751_2.png) [@danrib07](https://discourse.julialang.org/u/danrib07)
#### Post date: [June 11, 2021, 7:28pm UTC](https://discourse.julialang.org/t/binning-polar-values-with-julia/62754/4 "2021-06-11T19:28:34Z")

</div>

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

---

<div class="post-metadata">

### Author: ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)
#### Post date: [June 11, 2021, 8:46pm UTC](https://discourse.julialang.org/t/binning-polar-values-with-julia/62754/5 "2021-06-11T20:46:17Z")

</div>

@danrib07, you may have a look at code [here](https://github.com/anowacki/assorted-julia-modules/blob/master/CircPlot.jl).

---

<div class="post-metadata">

### Author: ![sethaxen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sethaxen/32/35604_2.png) [@sethaxen](https://discourse.julialang.org/u/sethaxen)
#### Post date: [June 11, 2021, 9:17pm UTC](https://discourse.julialang.org/t/binning-polar-values-with-julia/62754/6 "2021-06-11T21:17:12Z")

</div>

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

```julia
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))
end

# 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])
end

```

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

```julia
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))
end
# get the uncentered midpoints of the bins
midpoints = exp.(Ref(M), μ, midpoints_centered)

```

---

<div class="post-metadata">

### Author: ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)
#### Post date: [June 11, 2021, 10:38pm UTC](https://discourse.julialang.org/t/binning-polar-values-with-julia/62754/7 "2021-06-11T22:38:00Z")

</div>

@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?

Thanks.

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

---

<div class="post-metadata">

### Author: ![sethaxen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sethaxen/32/35604_2.png) [@sethaxen](https://discourse.julialang.org/u/sethaxen)
#### Post date: [June 11, 2021, 10:53pm UTC](https://discourse.julialang.org/t/binning-polar-values-with-julia/62754/8 "2021-06-11T22:53:00Z")

</div>

> [@rafael.guerra](#):
>
> @sethaxen, could you please elaborate a bit on the use of manifolds here?

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.

> [@rafael.guerra](#):
>
> Also, in `circdist()` what is the need for `one()` and `oftype()` , as the multiplication by `π` seems to always produce floats?

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.
