Javascript: удалить выбросы из массива?

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

Как я могу удалить выбросы, такие как 0, 57218, 60720 и 22684?

есть ли библиотека, которая может это сделать?

3 ответов


Это все зависит от вашего толкования что "выброс" есть. Общий подход:

  • высокие выбросы-это что-нибудь за пределами 3-го квартиля + 1.5 * межквартильный диапазон (IQR)
  • низкие выбросы-это все, что ниже 1-го квартиля-1.5 * IQR

это также подход, описанный компании Wolfram Mathworld.

Это легко обернуть в функцию :) я попытался написать ниже четко; очевидные возможности рефакторинга существуют. обратите внимание, что данный образец не содержит аномальных значений, используя этот общий подход.

function filterOutliers(someArray) {  

    // Copy the values, rather than operating on references to existing values
    var values = someArray.concat();

    // Then sort
    values.sort( function(a, b) {
            return a - b;
         });

    /* Then find a generous IQR. This is generous because if (values.length / 4) 
     * is not an int, then really you should average the two elements on either 
     * side to find q1.
     */     
    var q1 = values[Math.floor((values.length / 4))];
    // Likewise for q3. 
    var q3 = values[Math.ceil((values.length * (3 / 4)))];
    var iqr = q3 - q1;

    // Then find min and max values
    var maxValue = q3 + iqr*1.5;
    var minValue = q1 - iqr*1.5;

    // Then filter anything beyond or beneath these values.
    var filteredValues = values.filter(function(x) {
        return (x <= maxValue) && (x >= minValue);
    });

    // Then return
    return filteredValues;
}

Это улучшенная версия решения @james-peterson, которая обновляет синтаксис до текущего стандарта Javascript и добавляет более надежный способ поиска двух квартилей (реализованных в соответствии с формулами в https://de.wikipedia.org/wiki/Interquartilsabstand_ (Deskriptive_Statistik) ). Он использует более быстрый способ копирования массива (см.http://jsben.ch/wQ9RU Для сравнения производительности) и по-прежнему работает для q1 = q3.

function filterOutliers(someArray) {

  if(someArray.length < 4)
    return someArray;

  let values, q1, q3, iqr, maxValue, minValue;

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

  if((values.length / 4) % 1 === 0){//find quartiles
    q1 = 1/2 * (values[(values.length / 4)] + values[(values.length / 4) + 1]);
    q3 = 1/2 * (values[(values.length * (3 / 4))] + values[(values.length * (3 / 4)) + 1]);
  } else {
    q1 = values[Math.floor(values.length / 4 + 1)];
    q3 = values[Math.ceil(values.length * (3 / 4) + 1)];
  }

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

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

посмотреть этот суть: https://gist.github.com/rmeissn/f5b42fb3e1386a46f60304a57b6d215a


этот метод фактически не выполняется, если набор данных не содержит повторяющихся значений. Е. Г. 1, 2, 2, 2, 2, 2, 3, 10.

вот ссылка на демо (и источник):http://xcatliu.com/grubbs/