我试图计算一个平均值,而不是被一小组远距离数字(即1,2,1,2,3,4,50)抛弃,单个50将甩掉整个平均值。
如果我有这样的数字列表:
19,20,21,21,22,30,60,60
平均值 31
中位数 30
模式是21& 60(平均 40.5 )
但是任何人都可以看到大部分都在19-22(5英寸,3英寸)的范围内,如果你得到的只是主要范围的平均值,那么 20.6 (差异很大)以上数字)
我在想你可以这样:
C + d-R
c
是数字的计数,d
是不同的值,r
是范围。然后你可以将它应用于所有可能的范围,最高分是获得平均值的最佳范围。
例如19,20,21,21,22
将是5个数字,4个不同的值,范围是3(22 - 19)。如果你把它插入我的方程式,你得到5 + 4-3 = 6
如果您将此应用于整个数字列表,则为8 + 6-41 = -27
我认为这非常好用,但我必须创建一个巨大的循环来测试所有可能的范围。在我的小例子中,有21个可能的范围:
19-19,19-20,19-21,19-22,19-30,19-60,20-20,20-21,20-22,20-30,20-60,21-21 ,21-22,21-30,21-60,22-22,22-30,22-60,30-30,30-60,60-60
我想知道是否有更有效的方式来获得这样的平均值。
或者如果有人一起拥有更好的算法?
答案 0 :(得分:2)
这里可能会使用standard deviation,这基本上可以衡量数据点的集中程度。您可以将异常值定义为超出平均值的任何超过1个标准差(或任何其他适合您的数字),将它们抛出,并计算出不包含它们的新平均值。
答案 1 :(得分:2)
这是一个非常天真的实现,您可以根据自己的需要进行修复。我故意保持它非常冗长。它基于通常用于解决这些问题的五个数字摘要。
function get_median($arr) {
sort($arr);
$c = count($arr) - 1;
if ($c%2) {
$b = round($c/2);
$a = $b-1;
return ($arr[$b] + $arr[$a]) / 2 ;
} else {
return $arr[($c/2)];
}
}
function get_five_number_summary($arr) {
sort($arr);
$c = count($arr) - 1;
$fns = array();
if ($c%2) {
$b = round($c/2);
$a = $b-1;
$lower_quartile = array_slice($arr, 1, $a-1);
$upper_quartile = array_slice($arr, $b+1, count($lower_quartile));
$fns = array($arr[0], get_median($lower_quartile), get_median($arr), get_median($upper_quartile), $arr[$c-1]);
return $fns;
}
else {
$b = round($c/2);
$a = $b-1;
$lower_quartile = array_slice($arr, 1, $a);
$upper_quartile = array_slice($arr, $b+1, count($lower_quartile));
$fns = array($arr[0], get_median($lower_quartile), get_median($arr), get_median($upper_quartile), $arr[$c-1]);
return $fns;
}
}
function find_outliers($arr) {
$fns = get_five_number_summary($arr);
$interquartile_range = $fns[3] - $fns[1];
$low = $fns[1] - $interquartile_range;
$high = $fns[3] + $interquartile_range;
foreach ($arr as $v) {
if ($v > $high || $v < $low)
echo "$v is an outlier<br>";
}
}
//$numbers = array( 19,20,21,21,22,30,60 ); // 60 is an outlier
$numbers = array( 1,230,239,331,340,800); // 1 is an outlier, 800 is an outlier
find_outliers($numbers);
请注意,此方法虽然比标准偏差更容易实现,但不会在您的示例中找到两个60个异常值,但它的效果非常好。请使用代码,希望它有用!
要了解该算法的工作原理以及我如何实施该算法,请转到:http://www.mathwords.com/o/outlier.htm
当然,这并不是计算最终平均值,但是在你运行find_outliers()
之后它是微不足道的:P
答案 2 :(得分:1)
为什么不使用中位数?它不是30,它是21.5。
答案 3 :(得分:0)
您可以将值放入数组中,对数组进行排序,然后找到median,这通常是比平均值更好的数字,因为它会自动对异常值进行折扣,使得它们不会比其他任何值更重要数。
答案 4 :(得分:0)
您可以对数字进行排序,选择您喜欢的子范围(例如,中间的90%),并取其平均值。
你的问题没有一个真正的答案,因为总会有分布会给你一个有趣的答案(例如,考虑有偏见的双模态分布)。这就是为什么统计数据通常可以使用显示均值,中位数,四分位数和异常值的盒须图来表示。