我正在寻找有关计算加权中位数算法的良好学习资料和/或C++样例代码。我的中位数权重是介于0和1之间的值。您能否推荐一些链接?
double sum = 0;
int i;
for(i = 0; i < N; ++i)
{
sum += w[i];
if(sum > W/2)
break;
}
double median = x[i-1];
看来我回答这个问题有些草率,并犯了一些错误。我在R文档中找到了一个关于加权中位数的清晰描述,如下所述:
对于正权重
w = c(w[1], w[2], ..., w[n])
的n
个元素x = c(x[1], x[2], ..., x[n])
,使得sum(w) = S
,则加权中位数被定义为元素x[k]
,其中初始所有元素的总权重x[i] < x[k]
小于或等于S / 2
,所有元素的总权重x[i] > x[k]
小于或等于S / 2
。
从这个描述中,我们可以得到实现该算法的一个很简单的方法。如果我们从k == 0
开始,则没有元素在x[k]
之前,因此所有元素的总权重x[i] < x[k]
将小于S / 2
。根据数据,所有元素x[i] > x[k]
的总权重可能小于或大于S / 2
。所以我们可以通过遍历数组来移动到第二次总权重小于或等于S / 2
的位置。
#include <cstddef>
#include <numeric>
#include <iostream>
int main()
{
std::size_t const N = 5;
double x[N] = {0, 1, 2, 3, 4};
double w[N] = {.1, .2, .3, .4, .5};
double S = std::accumulate(w, w+N, 0.0); // the total weight
int k = 0;
double sum = S - w[0]; // sum is the total weight of all `x[i] > x[k]`
while(sum > S/2)
{
++k;
sum -= w[k];
}
std::cout << x[k] << std::endl;
}
请注意,如果中位数是最后一个元素(medianIndex == N-1
),那么sum==0
,因此条件sum>S/2
失败。 因此,k
将永远不会超出边界(除非N==0
!)。 此外,如果有两个元素满足条件,则算法总是选择第一个元素。[x[i-1], x[i])
中的任何值都是中位数。 - Ken Wayne VanderLindei-1
。那么如果 w[0]
是 0.9,会发生什么?在 break 时 i
是否会增加(否则你会得到 x[-1]
)?最好将 sum 初始化为 w[0]
并从 1 开始循环吗?不,那似乎也不对。抱歉,可能有点混淆。无论如何,我知道你的意思。 - andrew cooke template <typename VectorType>
auto sort_indexes(VectorType const& v)
{
std::vector<int> idx(v.size());
std::iota(std::begin(idx), std::end(idx), 0);
std::sort(std::begin(idx), std::end(idx), [&v](int i1, int i2) {return v[i1] < v[i2];});
return idx;
}
template<typename VectorType1, typename VectorType2>
auto weightedMedian(VectorType1 const& x, VectorType2 const& weight)
{
double totalWeight = 0.0;
for (int i = 0; i < static_cast<int>(x.size()); ++i)
{
totalWeight += weight[i];
}
auto ind = sort_indexes(x);
int k = ind[0];
double sum = totalWeight - weight[k];
for (int i = 1; i < static_cast<int>(ind.size()); ++i)
{
k = ind[i];
sum -= weight[k];
if (sum <= 0.5 * totalWeight)
{
break;
}
}
return x[k];
}
operator[](int)
和size()
的向量类型(因此不使用std::accumulate
等)。
[x,y]
并且想要计算加权中位数,其中y
是权重?请详细说明你的问题。 - Filip Roséen - refp