The mean and standard deviation of a sample of data can be thrown off if the sample contains one or many outlier(s) :


(image source)

For this reason, it is usually a good idea to check for and remove outliers before computing the mean or the standard deviation of a sample. To this aim, your function will receive a list of numbers representing a sample of data. Your function must remove any outliers and return the mean of the sample, rounded to two decimal places (round only at the end).

Since there is no objective definition of "outlier" in statistics, your function will also receive a cutoff, in standard deviation units. So for example if the cutoff is 3, then any value that is more than 3 standard deviations above or below the mean must be removed. Notice that, once outlying values are removed in a first "sweep", other less extreme values may then "become" outliers, that you'll have to remove as well!
Example :
```python
sample = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100]
cutoff = 3
clean_mean(sample, cutoff) → 5.5
```

Formula for the mean :

(where n is the sample size)

Formula for the standard deviation :

(where N is the sample size, xi is observation i and x̄ is the sample mean)

Note : since we are not computing the sample standard deviation for inferential purposes, the denominator is n, not n - 1.

Difficulty: introductory

Starter code:

def clean_mean(sample, cutoff):
	

Solutions:
def clean_mean(sample, cutoff):
    mean = sum(sample)/len(sample)
    dev = ((1/len(sample))*sum((num-mean)**2 for num in sample))**(1/2)
    cleaned = [num for num in sample if abs(num-mean) <= cutoff*dev]
    if sample==cleaned:
        return round(mean,2)
    else:
        return clean_mean(cleaned,cutoff)

from statistics import mean, pstdev

def clean_mean(sample, cutoff):
    cond = True
    while cond:
        _mean = mean(sample)
        _stdev = pstdev(sample)
        cut = [x for x in sample if abs(x-_mean)/_stdev <= cutoff]
        cond = len(sample) != len(cut)
        sample = cut
    return round(mean(sample),2)

from numpy import mean, std

def clean_mean(sample, cutoff):
    m, newMean = 1j, mean(sample)
    while m != newMean:
        m, sd = newMean, std(sample)
        sample = [s for s in sample if abs(s-m) < sd * cutoff]
        newMean = mean(sample)
    return round(newMean, 2)

from statistics import mean, pstdev

def clean_mean(sample, cutoff):
    u, v = mean(sample), pstdev(sample)
    cleaned = list(filter(lambda x: abs(x - u) <= cutoff*v, sample))
    if len(sample) == len(cleaned): return round(u, 2)
    return clean_mean(cleaned, cutoff)

import numpy as np

def clean_mean(sample, cutoff):
    sample = np.array(sample)
    while(True):
        m = np.mean(sample)
        newSample = sample[np.abs(sample - m) < cutoff * np.std(sample)]
        if (len(sample) == len(newSample)):
            return round(np.mean(newSample), 2)
        sample = newSample

def clean_mean(arr, cutoff):
    while True:
        mean, prev = sum(arr) / len(arr), arr
        S_D = (sum((i - mean) ** 2 for i in arr) / len(arr)) ** .5
        actual = S_D * cutoff
        arr = [i for i in arr if abs(i - mean) < actual]
        if prev == arr : return round(sum(arr)/len(arr),2)

import math
def clean_mean(sample, cutoff):
    print(sample, cutoff)
    while True:
        a=len(sample)
        total=sum(sample)
        mean=total/len(sample)
        new_list=[(i-mean)**2 for i in sample]
        total_new_list=sum(new_list)
        sd=math.sqrt(total_new_list/len(sample))
        sample=[i for i in sample if i<cutoff*sd+mean and i>mean-cutoff*sd]
        if a==len(sample):
            break
    print (round(mean,2))
    return round(mean,2)

from statistics import *
def clean_mean(sample, cutoff):
    prev_mn, mn, sd = None, mean(sample), pstdev(sample)
    while mn != prev_mn:
        sample = [e for e in sample if mn-cutoff*sd < e < mn+cutoff*sd]
        prev_mn, mn, sd = mn, mean(sample), pstdev(sample)
        
    return round(mn, 2)


from statistics import mean, pstdev

def clean_mean(sample, cutoff):
    n = 0
    while n != len(sample):
        n = len(sample)
        mu = mean(sample)
        sigma = pstdev(sample, mu)
        sample = [x for x in sample if abs(x - mu) < cutoff * sigma]
    return round(mu, 2)

def clean_mean(sample, cutoff):
    if not sample:
        return 0
    samplesize = len(sample)
    print((samplesize, sample))
    mean = sum(sample) / samplesize
    stddev = ((samplesize ** -1) * sum((element - mean) ** 2 for element in sample)) ** 0.5
    cutoffpos = mean + cutoff * stddev
    cutoffneg = mean - cutoff * stddev
    for element in sample[:]:
        if element > cutoffpos or element < cutoffneg:
            sample.remove(element)
    if samplesize == len(sample):
        return round(mean, 2)
    else:
        return clean_mean(sample, cutoff)