5
$\begingroup$

looking to draw on some of your wisdom around modified z-scores as used for detecting outliers.

As far as I can tell from my research, when a distribution might not be normal (e.g. skewed), a modified z-score is a better indicator of outliers than z-score itself. This is because instead of mean it uses median which is a robust estimator of central tendancy if the distribution is not known to be normal.

I am testing both of these plus some other outlier detection algorithms against a list of values where I know one value is an extreme outlier. To help me I created a small python program that calculates both z-scores and modified z-scores against that list and then uses that to check whether any of the items in the list look like outliers. Basically, I was checking those algorithms would successfully detect the extreme outlier I know is there.

To check the distribution of my data the program creates a box plot, the outlier (value = 200) is clearly evident. For reference, the median of this dataset is 58.

boxplot of data

The modified z-score for the outlier value of 200 is only 2.81 and this is substantially lower than the 3.5 for consideration as an outlier, hence it does not get labelled as an outlier. FYI, I used 3.5 because that seems to the most recommended value for the cut-off.

The z-score for the outlier value of 200 is 3.40 and this is above the 3.0 for consideration as an outlier, hence it does get labelled as an outlier. FYI, I used 3.0 as the cut-off as that seemed most popular.

My question is, why does the z-score algorithm detect the outlier in my datasets when the modified z-score algorithm does not? This seems counter-intuitive to me, especially as the outlier is obvious from the box plot.

Here is my python in case that is where I have made an error:

import matplotlib as plt
import numpy as np
from scipy.stats import zscore

def z_score_mod(obs):
    # modified z-score = 0.6745(xi – x̃) / MAD
    med = np.median(obs)
    med_abs_dev = np.median(np.abs(obs - med))
    z_score_mod = 0.6745 * ((obs - med) / med_abs_dev)
    return z_score_mod
    
# list of observations with reasonably large outlier value = 200 and index = 13
list_of_obs = [58,71,11,18,90,97,15,53,39,22,62,51,10,200,20,64,94,71,73,18,95,96,92,38,26]

# Convert list of observations to numpy array
array_of_obs = np.array(list_of_obs)

# Create box plot to show the outlier
plt.pyplot.boxplot(array_of_obs)

median = np.median(array_of_obs)

# Calculate modified z-score for each array item
array_of_z_score_mod = z_score_mod(array_of_obs)

# For the modified z-scores generated, determine if any are outliers
array_of_outlier_evals = abs(array_of_z_score_mod) > 3.5

# Is the observation value = 200 at index = 13 an outlier?
print('\r')
print(f'Observation at index position 13 = {list_of_obs[13]}')
print(f'Modified z-score of value = {array_of_z_score_mod[13]:.2f}')
print(f'At modified z-score threshold 3.5 is value an outlier : {array_of_outlier_evals[13]}')

# Calculate z-score for each array item
array_of_z_score = zscore(list_of_obs)

# For the z-scores generated, determine if any are outliers
array_of_outlier_evals_2 = abs(array_of_z_score) > 3

# Is the observation value = 200 at index = 13 an outlier?
print('\r')
print(f'Observation at index position 13 = {list_of_obs[13]}')
print(f'z-score of value = {array_of_z_score[13]:.2f}')
print(f'At z-score threshold 3.0 is value an outlier : {array_of_outlier_evals_2[13]}')
$\endgroup$
7
  • 1
    $\begingroup$ Can you edit the post to include a formula for the modified z-score? $\endgroup$ Commented Aug 2 at 17:42
  • 3
    $\begingroup$ There are better methods to flag outlying data. They vary depending on how many outliers you need to find, in which direction(s), on the purpose of the flagging, and so on. One principle they have in common is to use estimates of location and spread that do not depend on the possible outliers themselves. You might therefore be better off researching these methods rather than pursuing your current approach. $\endgroup$
    – whuber
    Commented Aug 2 at 17:51
  • 1
    $\begingroup$ @whuber Median and MAD do not depend on the outlier in a problematic way here - that's not the problem with modified z-scores in this situation. In fact in the robustness literature outlier identification based on median/MAD is something of a gold standard. $\endgroup$ Commented Aug 2 at 20:21
  • 3
    $\begingroup$ @Christian Not quite. What you say is generally true for sufficiently large datasets, but for the smallish ones--a handful to at most a few hundred univariate observations--it doesn't apply as well as we might think. See the chapter on outliers in Madansky's book Prescriptions for Working Statisticians for a summary from a third of a century ago or Vic Barnett's text on outliers from before then. $\endgroup$
    – whuber
    Commented Aug 2 at 20:57
  • 1
    $\begingroup$ Are these real data? Is there a reason the values are integer? What constitutes an outlier depends on the type of process. For example, on a multiplicative scale, $200$ does not seem very far from the rest at all. $\endgroup$ Commented Aug 3 at 4:49

1 Answer 1

4
$\begingroup$

I had a look at your data. The distributional shape of the non-outliers doesn't have that many points in the middle, and relatively many points are in good distance from the median. This means that for these data the MAD (with the usual normalisation constant, i.e., dividing by 0.6745), is considerably larger than the standard deviation (sd), and therefore the modified z-score has a harder time finding the outlier. Generally median and MAD are not so good if the density is low around the median and higher further away. Note in particular that there are many points around 95, so that the MAD (based on the closest half of points to the median) still makes use of these. The MAD then ignores what happens between 95 and 200. If data were from a normal distribution, you'd still expect quite a few points there, but here there is a big hole, which makes the outlier outlying.

It is a nice example and indeed counter-intuitive. The outlier is chosen just so that it doesn't make the sd explode enough, but the remainder is chosen so that is messes up the MAD. If you put the outlier even higher up, the sd will become larger and the MAD won't, so median/MAD will more clearly show such points as outliers.

Non-modified z-scores can find a single outlier in this way - a major advantage of median/MAD is that they still work with larger numbers of outliers.

$\endgroup$
7
  • $\begingroup$ thank you for your answer which I do find helpful. Do you think I should in future also consider whether the coeffiecient of variation (0.6745) is good factor to use or is there an alternative value/formula [ e.g. cqv = (Q3 - Q1) / (Q3 + Q1) ]? $\endgroup$
    – gecko
    Commented Aug 5 at 8:29
  • $\begingroup$ (+1) If there were good simple rules for outlier identification, they would have been discovered and publicised long ago. Needing to automate outlier identification is a problem for many people but when it arises it's best treated as a multivariate problem, not using over-simplified rules of thumb. Also subject-matter knowledge is not just invaluable, but using it essential for good practice. Hence many supposed outliers are just bona fide data points in skewed distributions. $\endgroup$
    – Nick Cox
    Commented Aug 5 at 8:51
  • $\begingroup$ Agree with your sentiments @NickCox. I stated from the outset of my question, "I am testing both of these plus some other outlier detection algorithms". It is the classic case of "if I were you I wouldn't start from here" and start I must. In the absence of deep subject matter knowledge and an ultimate understanding for statistical rules of engagement, I'll persevere with various explorations, including those you suggested. Happy to consider suggestions if they help expand my knowledge, e.g. suggestions for practical approaches to outlier identification and treatment. $\endgroup$
    – gecko
    Commented Aug 5 at 10:16
  • $\begingroup$ What you want to do is never what I need or want to do, so I don't have positive suggestions beyond graphing the data and thinking about it. Sorry if that sounds smug, but it is genuine. $\endgroup$
    – Nick Cox
    Commented Aug 5 at 11:10
  • 1
    $\begingroup$ @gecko I don't think the value of 0.6745 is the problem. Of course in this example you'd be better off with a different one, but then if you assume you know that this is an outlier anyway, you don't need to tailor a method to find it. The Median/MAD rule is often fine and rarely goes wrong, but here it does... $\endgroup$ Commented Aug 5 at 20:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.