Javascript: remove outlier from an array?

Viewed 13153
values = [8160,8160,6160,22684,0,0,60720,1380,1380,57128]

how can I remove outliers like 0, 57218, 60720 and 22684?

Is there a library which can do this?

5 Answers

I had some problems with the other two solutions. Problems like having NaN values as q1 and q3 because of wrong indexes. The array length needs to have an -1 because of the 0 index. Then it is checked if the index is a int or decimal, in the case of a decimal the value between two indexes is extracted.

function filterOutliers (someArray) {
    if (someArray.length < 4) {
        return someArray;
    }

    let values = someArray.slice().sort((a, b) => a - b); // copy array fast and sort

    let q1 = getQuantile(values, 25);
    let q3 = getQuantile(values, 75);

    let iqr, maxValue, minValue;
    iqr = q3 - q1;
    maxValue = q3 + iqr * 1.5;
    minValue = q1 - iqr * 1.5;

    return values.filter((x) => (x >= minValue) && (x <= maxValue));
}

function getQuantile (array, quantile) {
    // Get the index the quantile is at.
    let index = quantile / 100.0 * (array.length - 1);

    // Check if it has decimal places.
    if (index % 1 === 0) {
        return array[index];
    } else {
        // Get the lower index.
        let lowerIndex = Math.floor(index);
        // Get the remaining.
        let remainder = index - lowerIndex;
        // Add the remaining to the lowerindex value.
        return array[lowerIndex] + remainder * (array[lowerIndex + 1] - array[lowerIndex]);
    }
}

Here is the implementation to filter upper outliers from a given collection. This approach follows a similar methodology as the provided answers above.

The if case will be checking the length of collection if it is 4n or 4n + 1. In that case, we need to get an average of two elements to have our quartiles.

4n and 4n+1 cases

Otherwise, in cases of 4n + 2 and 4n + 3, we directly can access the upper/lower quartile.

4n+2 and 4n+3 cases


const outlierDetector = collection => {
    const size = collection.length;

    let q1, q3;

    if (size < 2) {
        return collection;
    }

    const sortedCollection = collection.slice().sort((a, b) => a - b);

    if ((size - 1) / 4 % 1 === 0 || size / 4 % 1 === 0) {
        q1 = 1 / 2 * (sortedCollection[Math.floor(size / 4) - 1] + sortedCollection[Math.floor(size / 4)]);
        q3 = 1 / 2 * (sortedCollection[Math.ceil(size * 3 / 4) - 1] + sortedCollection[Math.ceil(size * 3 / 4)]);
    } else {
        q1 = sortedCollection[Math.floor(size / 4)];
        q3 = sortedCollection[Math.floor(size * 3 / 4)];
    }

    const iqr = q3 - q1;
    const maxValue = q3 + iqr * 1.5;

    return sortedCollection.filter(value => value >= maxValue);
};

Related