# Frequency counts on a square lattice

**URL:** https://discourse.julialang.org/t/frequency-counts-on-a-square-lattice/46533
**Category:** Performance
**Created:** [September 13, 2020, 2:50am UTC](https://discourse.julialang.org/t/frequency-counts-on-a-square-lattice/46533 "2020-09-13T02:50:59Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![gideonsimpson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gideonsimpson/32/1928_2.png) [@gideonsimpson](https://discourse.julialang.org/u/gideonsimpson)
#### Post date: [September 13, 2020, 2:50am UTC](https://discourse.julialang.org/t/frequency-counts-on-a-square-lattice/46533/1 "2020-09-13T02:50:59Z")

</div>

I have a square array, `c`, with integer entries that I expect to repeat. I would like to get frequency counts on the different indices, as they represent categorical data. I was wondering what might be the most efficient way to do this. I know that I could flatten the array and use `DataFrames.jl`, but I have to do this many times, so I’m concerned about introducing unnecessary overhead through those conversions (square array to flat array to data frame).

---

<div class="post-metadata">

### Author: ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)
#### Post date: [September 13, 2020, 5:25am UTC](https://discourse.julialang.org/t/frequency-counts-on-a-square-lattice/46533/2 "2020-09-13T05:25:58Z")

</div>

Something like this?

```julia

julia> using StatsBase

julia> M = rand(1:10, 10, 10)
10×10 Array{Int64,2}:
 8 8 6 7 5 9 5 10 5 7
 5 1 7 3 10 9 8 4 8 2
 2 2 3 9 2 7 9 4 8 7
 4 6 8 3 6 2 10 5 3 6
 8 7 7 6 3 8 1 4 6 6
 6 3 5 5 9 6 7 1 7 5
 1 4 7 9 5 8 4 2 5 1
 6 8 6 7 3 5 1 2 8 10
 6 2 9 7 3 6 7 2 6 2
 5 9 9 10 4 2 6 7 9 1

julia> StatsBase.countmap(vec(M))
Dict{Int64,Int64} with 10 entries:
  7 => 14
  4 => 7
  9 => 10
  10 => 5
  2 => 11
  3 => 8
  5 => 12
  8 => 11
  6 => 15
  1 => 7

```

---

<div class="post-metadata">

### Author: ![gideonsimpson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gideonsimpson/32/1928_2.png) [@gideonsimpson](https://discourse.julialang.org/u/gideonsimpson)
#### Post date: [September 13, 2020, 12:29pm UTC](https://discourse.julialang.org/t/frequency-counts-on-a-square-lattice/46533/3 "2020-09-13T12:29:53Z")

</div>

Works for me.

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [September 13, 2020, 3:04pm UTC](https://discourse.julialang.org/t/frequency-counts-on-a-square-lattice/46533/4 "2020-09-13T15:04:57Z")

</div>

Note that if you know in advance that you have limited set of entries, e.g. values in `1:10`, then you can do much better than `countmap` just by allocating an array of counts and incrementing it as you iterate through your data. For your example above, I get a speedup by more than a factor of 5:

```julia
julia> function countmap10(M)
           counts = zeros(Int, 10)
           for x in M
               counts[x] += 1
           end
           return counts
       end

julia> @btime StatsBase.countmap(vec($M))
  628.174 ns (8 allocations: 1.70 KiB)
Dict{Int64,Int64} with 10 entries:
  7 => 14
  4 => 7
  9 => 10
  10 => 5
  2 => 11
  3 => 8
  5 => 12
  8 => 11
  6 => 15
  1 => 7

julia> @btime countmap10($M)
  115.560 ns (1 allocation: 160 bytes)
10-element Array{Int64,1}:
  7
 11
  8
  7
 12
 15
 14
 11
 10
  5

```

---

<div class="post-metadata">

### Author: ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)
#### Post date: [September 13, 2020, 3:20pm UTC](https://discourse.julialang.org/t/frequency-counts-on-a-square-lattice/46533/5 "2020-09-13T15:20:36Z")

</div>

should countmap be able to take an optional AbstractArray as possible set?

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [September 13, 2020, 3:22pm UTC](https://discourse.julialang.org/t/frequency-counts-on-a-square-lattice/46533/6 "2020-09-13T15:22:30Z")

</div>

It seems like there should be a `countmap!(counts, array)` function that takes any `counts` object supporting `getindex/setindex!` (e.g. a `Dict` or an array or some other data structure).

---

<div class="post-metadata">

### Author: ![anon92994695](https://avatars.discourse-cdn.com/v4/letter/a/ce7236/32.png) [@anon92994695](https://discourse.julialang.org/u/anon92994695)
#### Post date: [September 13, 2020, 3:29pm UTC](https://discourse.julialang.org/t/frequency-counts-on-a-square-lattice/46533/7 "2020-09-13T15:29:31Z")

</div>

If you have too many counts to stick into memory I really recommend OnlineStats.jl’s countmap :). [https://github.com/joshday/OnlineStats.jl](https://github.com/joshday/OnlineStats.jl)

[https://joshday.github.io/OnlineStats.jl/latest/api/#OnlineStatsBase.CountMap](https://joshday.github.io/OnlineStats.jl/latest/api/#OnlineStatsBase.CountMap)
