Black and White Texas Instruments calculator

Calculate the mode & median averages of a Ruby array

I’ve previously disscussed a way to calculate the mean of an array in Ruby. But there are two other averages that you might see, less commonly used, but still useful.

Calculate a median…

a = [1, 3, 2, 4, 6, 5, 7, 8]

sorted = a.sort # required
#=> [1, 2, 3, 4, 5, 6, 7, 8]
midpoint = a.length / 2 # integer division
#=> 4
if a.length.even?
  # median is mean of two values around the midpoint
  sorted[midpoint-1, 2].sum / 2.0
else
  sorted[midpoint]
end
#=> 4.5

Calculate a mode…

…using Array#tally then sorting:

a = [1, 3, 3, 4, 6, 5, 7, 8]

tallied = a.tally
#=> {1=>1, 3=>2, 4=>1, 6=>1, 5=>1, 7=>1, 8=>1}
top_pair = tallied.sort_by { |_,v| v }.last(2)
#=> [[8, 1], [3, 2]]
if top_pair.size == 1
  top_pair[0][0] # only one element, it is the mode
elsif top_pair[0][1] == top_pair[1][1]
  nil # if count is same, no mode.
else
  top_pair[1][0]
end
#=> 3

Why?

The #tally method was added to Enumerable in Ruby 2.7 so you might see implementations that use inject, which will perform worse.

I compared the performance of using native Ruby methods versus your own implementations when I wrote about calculating the mean.

Anything else?

It’s no doubt a good idea to further encapsulate these calulations into methods.

If you’re doing a lot of this sort of calculation or in a situation where performance is important you should look at the enumerable-statistics gem. It has natively implemented versions of several statistical summary methods mixed into Array and Enumerable.

The implementation in C means these methods are much faster than any version of the algorithm programmed in Ruby.


last updated on 21 Jun 2021 by @andycroll

photo by
Ray Reyes

Don’t miss my next post, sign up to the One Ruby Thing email and get my next post in your inbox.

Don’t miss my next post, sign up to the One Ruby Thing email and get my next post in your inbox.