/***************************************************************************
Description : Calculates the trimmed mean of the data.
Comments : trim defaults to 0. Trim = 0.5 now gives the median.
***************************************************************************/
Real StatData::mean(Real trim) const
{
check_trim(trim);
if (size() < 1)
err << "StatData::mean: no data" << fatal_error;
Real result = 0;
const_cast<StatData&>(*this).items.sort();
int low = (int)(size()*trim); // starting at 0
int high = size() - low;
if (low == high) {
low--; high++;
}
for(int k = low; k < high; k++)
result += items[k];
ASSERT(2*low < size()); // Make sure we're not dividing by zero.
return result / (size() - 2*low);
}
我有三个问题要问:
1)*this
是否引用了StatData?
2)为什么ASSERT(2*low < size())
检查没有除以零?
3)平均值通常表示总和除以总大小。但为什么我们要做size()-2*low
?
答案 0 :(得分:3)
在开始之前,让我们花一点时间来解释参数trim
是什么。
trim
表示在您想要计算所需内容之前,希望从数据的两端切断多少数据,假设这是按排序顺序排列的。通过做trim = 0.5
,除了考虑中间值(即中位数)之外,你正在削减一切。例如,通过执行trim = 0.1
,将丢弃前10%和最后10%的数据,并且只计算剩余80%数据中的平均值。请注意,这是[0,1]
之间的归一化分数。然后将此分数乘以size()
,以确定在计算均值时需要从数据中的哪个索引开始 - 由low
表示,以及停止在哪个索引 - 由{{1}表示}。 high
只是由high
计算,因为双方切断的数据量需要是对称的。实际上这有时被称为 alpha修饰平均值,或者通常称为truncated mean。它之所以被称为alpha修剪平均值,是因为alpha定义了要从排序数据的开头和结尾切掉多少分数。在我们的例子中,size() - low
。
现在回答你的问题。
alpha = trim
指的是当前类的实例,类型为*this
,并且最终尝试访问StatData
,它似乎是一个包含一些数字的容器类型为items
。但是,正如Neil Kirk在他的评论中解释的那样,以及我所说的嗨,这是一种使用Real
的非常不安全的方式,以便您能够访问{{1}这样你就可以对这些项进行排序。这非常糟糕。
这基本上是为了确保在您计算平均值时,您不会将其除以零。这种情况永远不会是const_cast
,因为您的数据大小永远不会高于此点。他们会检查items
是否确保您要将数据总和除以> 2*low
,这是我们对算术平均值的期望。如果这种情况失败,这意味着无法计算平均值,它应该输出错误。
您要除size() < 2*low
,因为您正在使用> 0
来放弃您不需要的数据开头和结尾的数据比例。这与一侧的size() - 2*low
和另一侧的trim
完全对应。请注意low
计算我们需要在高端停止累积的位置,此点之后存在的数据比例为low
。因此,消除的这些比例的组合为high
,这就是为什么您需要从low
中减去此值,因为您不再使用该数据。
答案 1 :(得分:1)