加权中位数计算
Weighted median computation
我正在寻找有关C++计算加权中值算法和/或示例代码的良好学习材料。我的中位数的权重是 0 到 1 之间的值。你能推荐我一些链接吗?
加权中位数定义如下:
如果 x
是 N
个元素的排序数组,而w
是总权重W
的权重数组,则加权中位数是最后一个x[i]
使得 w[i]
和所有先前权重的总和小于或等于 S/2
。
在C++中,这可以这样表示(假设x
、w
和W
被定义为上面(
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 文档中找到了加权中位数的简洁描述,描述如下:
对于
n
元素x = c(x[1], x[2], ..., x[n])
正 权重w = c(w[1], w[2], ..., w[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
!此外,如果有两个元素满足条件,则算法始终选择第一个元素。
下面是最初未排序向量的加权中位数的实现。它建立在 @Ken Wayne VanderLinde 对中位数计算的非常好的答案以及此线程中给出的索引排序器的基础上。
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
等(。
- 在计算中使用二的幂有多有利可图
- 在 1.5 秒内找到 3 到 4 个不同整数的中位数超过 2000 万
- 十进制的中位数是多少?
- 如何使用第一个、中间和最后一个元素的中位数正确分区?
- 如何在长时间计算中进行C 的一次进度更新
- 使用 boost::累加器::统计来查找数组的中位数
- 从向量中提取最小值、最大值和中位数的最有效方法是什么
- Q学习计算中的大量状态
- 如何处理计算中的"unsigned long long int"?
- 我可以在Apache Ignite计算中混合使用C++和Java吗?
- 如果方法是常量,如何找到向量的中位数?
- 多线程蒙特卡罗计算中没有加速
- 在C++中实现两个大小相等的排序数组的中位数
- 可以在CUDA速度计算中实现TensorFlow自定义OP梯度
- 查找一组循环数据的中位数
- 为什么我的中位数快速选择算法segfault
- 是否可以实施中位数的中位数intreselect而没有掉期或堆的分配
- 如何在 c++ 中计算整数位数
- C++使用参考计算中位数
- 加权中位数计算