Javascript:从数组中删除离群值?
如何删除异常值,如0、57218、60720和22684Javascript:从数组中删除离群值?,javascript,statistics,Javascript,Statistics,如何删除异常值,如0、57218、60720和22684 是否有一个库可以做到这一点?这一切都取决于您对“异常值”的解释。一个共同的做法是: 高异常值是指超出第三个四分位数+1.5*的任何值 四分位间距(IQR) 低异常值是低于第一个四分位数-1.5*IQR的任何值 这也是所描述的方法 这很容易用一个函数来概括:)我试着把下面的内容写清楚;明显的重构机会确实存在请注意,使用此常用方法,给定的样本不包含任何外围值 values = [8160,8160,6160,22684,0,0,60720
是否有一个库可以做到这一点?这一切都取决于您对“异常值”的解释。一个共同的做法是:
- 高异常值是指超出第三个四分位数+1.5*的任何值 四分位间距(IQR)
- 低异常值是低于第一个四分位数-1.5*IQR的任何值
values = [8160,8160,6160,22684,0,0,60720,1380,1380,57128]
函数过滤器输出器(someArray){
//复制值,而不是对现有值的引用进行操作
var values=someArray.concat();
//然后分类
值。排序(函数(a,b){
返回a-b;
});
/*然后找到一个慷慨的IQR。这是慷慨的,因为如果(value.length/4)
*不是int,那么实际上你应该平均这两个元素
*一边去找q1。
*/
var q1=数值[Math.floor((values.length/4))];
//第三季度也是如此。
var q3=数值[Math.ceil((values.length*(3/4))];
var iqr=q3-q1;
//然后找到最小值和最大值
var maxValue=q3+iqr*1.5;
var minValue=q1-iqr*1.5;
//然后过滤超出或低于这些值的任何内容。
var filteredValues=values.filter(函数(x){
返回值(x=最小值);
});
//然后返回
返回filteredvalue;
}
这是@james-peterson解决方案的改进版本,它将语法更新为当前的Javascript标准,并添加了一种更健壮的查找两个四分位数的方法(根据
)。它使用更快的方式复制阵列(有关性能比较,请参阅),并且在q1=q3时仍然有效
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;
}
函数过滤器输出器(someArray){
if(someArray.length<4)
返回数组;
let值,q1,q3,iqr,maxValue,minValue;
values=someArray.slice().sort((a,b)=>a-b);//快速复制数组并排序
如果((values.length/4)%1==0){//find quartiles
q1=1/2*(值[(values.length/4)]+值[(values.length/4)+1];
q3=1/2*(值[(values.length*(3/4))]+值[(values.length*(3/4))+1]);
}否则{
q1=数值[数学楼层(数值长度/4+1)];
q3=数值[Math.ceil(values.length*(3/4)+1)];
}
iqr=q3-q1;
maxValue=q3+iqr*1.5;
minValue=q1-iqr*1.5;
返回值。筛选器((x)=>(x>=minValue)&&(x如果数据集包含重复的值,则此方法实际上会失败。例如1、2、2、2、2、3、10
我和它斗争了一段时间,但后来我发现了一种叫做Grubbs'test的东西。到目前为止,它似乎是可靠的,至少在我的案例中是如此
这里有一个指向演示(和源代码)的链接:其他两种解决方案存在一些问题。例如,由于索引错误,NaN值为q1和q3。由于索引为0,数组长度需要有-1。然后检查索引是int还是decimal,如果是decimal,则提取两个索引之间的值
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));
}
函数过滤器输出器(someArray){
if(someArray.length<4){
返回数组;
}
让value=someArray.slice().sort((a,b)=>a-b);//快速复制数组并排序
设q1=getQuantile(值,25);
设q3=getQuantile(值75);
设iqr、maxValue、minValue;
iqr=q3-q1;
maxValue=q3+iqr*1.5;
minValue=q1-iqr*1.5;
返回值.filter((x)=>(x>=minValue)和&(x这里是从给定集合中筛选较高异常值的实现。此方法遵循与上面提供的答案类似的方法
if
案例将检查收集长度,如果它是4n
或4n+1
。在这种情况下,我们需要得到两个元素的平均值才能得到四分位数
否则,在4n+2
和4n+3
的情况下,我们可以直接访问上/下四分位数
常量异常检测器=集合=>{
const size=collection.length;
让q1,q3;
如果(尺寸<2){
回收;
}
const sortedCollection=collection.slice().sort((a,b)=>a-b);
如果((大小-1)/4%1==0 | |大小/4%1==0){
q1=1/2*(分类收集[数学地板(尺寸/4)-1]+分类收集[数学地板(尺寸/4)];
q3=1/2*(分类收集[Math.ceil(尺寸*3/4)-1]+分类收集[Math.ceil(尺寸*3/4)];
}否则{
q1=分类收集[数学地板(尺寸/4)];
q3=分类收集[数学地板(尺寸*3/4)];
}
常数iqr=q3-q1;
常数maxValue=q3+iqr*1.5;
返回sortedCollection.filter(值=>value>=maxValue);
};
您可能需要检查此答案:。如果您想签出库,则有下划线。请参阅此答案以获取示例:您也可以查看此库它是否工作?我尝试了过滤器输出器([81608160616022684,0,0607201380138057128,1000000000000])
并且它返回完全相同的数组。上面代码中有轻微的逻辑错误。过滤器应该返回(xminValue);如果q1==q3,则返回空数组。应该返回(x=minValue)
[4421351235126601227581202350122320,172125]
没有删除17
这怎么可能?当然17
在这里是一个异常值?@Frank:17不是一个异常值。数组(1st.Quadrant-1.5*(IQR))
的下限比17低得多。第二个条件对于数组长度<7的任何东西都不起作用,因为q3最终超出了界限,即Math.ceil(7*(3/4)+1)=7
.AMath.min
应该可以解决它,我猜在
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]);
}
}