How to get single median in numpy masked array with even number of entires

Viewed 334

I have a numpy masked nd-array. I need to find the median along a specific axis. For some cases, I end up having even number of elements, in which case numpy.ma.median gives average of the middle two elements. However, I don't want the average. I want one of the median elements. Any one of the two is fine. How do I get this?

MWE:

>>> import numpy
>>> data=numpy.arange(-5,10).reshape(3,5)
>>> mdata=numpy.ma.masked_where(data<=0,data)
>>> numpy.ma.median(mdata, axis=0)
masked_array(data=[5.0, 3.5, 4.5, 5.5, 6.5],
             mask=[False, False, False, False, False],
       fill_value=1e+20)

As you can see, it is averaging (1 and 6) and providing fractional values (3.5). I want any one of 1 or 6.

3 Answers

For even number of elements, the median returns the average of two middle numbers. However, if you don't want the average, just want one any of the two middle numbers, you can drop an element from your collection while calling the median method which will make length of collection odd, and you will you'll get what you want, not the average (though it is not a proper way to find median)

It is expected to average out when you have even number of elements. Suppose you have array of elements from 1 to 10. The the mean is expected to be average of 5 and 6 which is 5.5. If you have elements from 1 to 11 then median is 6. Hope this clarifies

  • numpy.percentile(array, 50) gives median value.
  • numpy.percentile has an option to specify interpolation to nearest.
  • However this function is not available in numpy.ma module.
  • The trick used in this answer can be used here.

The idea is to fill invalid values with nan and use numpy.nanpercentile() with nearest interpolation.

>>> mdata1 = numpy.ma.filled(mdata.astype('float'), numpy.nan)
>>> numpy.nanpercentile(mdata1, 50, axis=0, interpolation='nearest')
array([5., 1., 2., 3., 4.])
Related