我有一个有趣的Javascript任务(在Node.js,FWIW中执行):我需要获取数据集的“加权中位数”,我有值(收入,在这种情况下)和每个的权重。例如:
income #people
0 5
16000 3
20000 8
32000 4
40000 3
41000 1
50000 2
90000 1
换句话说,8人赚20美元,2人赚5万美元等。我需要“加权中位数” - 所有27人的中位数。
执行此操作的天真方法是创建一个数组并将其与每个值一起播种,如下所示:
var incomes = [0, 0, 0, 0, 0, 16000, 16000, 16000, 20000, 20000, 20000, 20000, 20000, 20000, 20000, 20000, 32000, 32000, 32000, 32000, 40000, 40000, 40000, 41000, 50000, 50000, 90000];
然后可以轻松获取此数组的中位数(即20,000美元)。实际上,我有每个样本7,000到14,000人的数据。虽然我确信Node可以处理这么大的数组,但感觉非常邋。。
我目前的解决方案是计算假设的详细数组中的中值的索引 - 在这种情况下为13 - 并且通过收入和权重数组循环,累计累计权重直到达到或超过中途点。这是一个简化的例子。 (显然,中位数对偶数列表的规则要求略有不同。这只是一个POC。)
var halfway = 13,
progress = 0;
var vals = [[0,5], [16000,3], [20000,8], [32000,4], [40000,3], [41000,1], [50000,2], [90000,1]];
for (var v = 0; v < vals.length; v += 1) {
progress += vals[v][1];
if (progress >= halfway) {
var median = vals[v][0];
break;
}
}
这样可以正常工作,但是当你想要开始计算四分位数时它会变得混乱。更简单的是,我能够在详细数组中的适当位置创建值的稀疏数组,而不填充所有中间值,然后对此数组执行查找以获取最大值的索引。但是我需要一些有效的机制来查找稀疏数组中的先前已知索引,如果(很可能)我在备用数组中寻找的索引没有填充。
这似乎是一个相当普遍的问题。
答案 0 :(得分:1)
就计算效率而言,我认为你所拥有的就像你要得到的一样好,虽然我不确定你面对四分位数有什么困难(抱歉太低代表要求澄清)。
让我们先看看你所拥有的效率。你有一个长度为n的数组,你逐步通过它添加到一个计数器并中途中断(我假设已经给出了中途信息,再次抱歉太低而无法问)。看着简单的O(n)就好了。
现在你建议的是某种形式的查找,给定索引知道最近的填充索引O(1)。那会更好,所以让我们看看我们需要什么。好吧,我们需要通过循环将给定的数据移动到一些新的数据结构中......哦,这意味着回到O(n)。
故事的道德你所拥有的是好的,好的工作。