Javascript:从数组中删除异常值?

jav*_*ent 8 javascript statistics

values = [8160,8160,6160,22684,0,0,60720,1380,1380,57128]
Run Code Online (Sandbox Code Playgroud)

如何删除0,57218,60720和22684等异常值?

有没有可以做到这一点的图书馆?

Jam*_*son 18

这一切都取决于你的解释什么是"异常"的说法.一种常见的方法:

  • 高异常值超出第三四分位数+ 1.5*四分位数范围(IQR)
  • 低离群值低于第一四分位数 - 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;
}
Run Code Online (Sandbox Code Playgroud)

  • 它到底有用吗?我尝试了“filterOutliers([8160,8160,6160,22684,0,0,60720,1380,1380,57128, 1000000000000])”,它返回完全相同的数组。 (3认同)
  • `[4421, 3512, 5126, 6012, 7581, 2023, 5012, 2320, 17, 2125]` 没有删除 `17` 这是怎么回事?当然“17”在这里是一个异常值? (2认同)
  • @Frank:17 不是异常值。数组的下限 `(1st.Quadrant - 1.5 * ( IQR ))` 远低于 17。 (2认同)

Roy*_*Roy 9

这是@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));
}
Run Code Online (Sandbox Code Playgroud)

请参阅此要点:https : //gist.github.com/rmeissn/f5b42fb3e1386a46f60304a57b6d215a