需要计算分配的百分比

时间:2014-05-07 09:23:56

标签: math average distribution

我有一组给定属性的数字:

red    = 4
blue   = 0
orange = 2
purple = 1

我需要计算分配百分比。意思是,选择有多么多样?是20%多样化?是100%多样化(意味着说4,4,4,4的均匀分布)?

我试图创造一个接近100%的性感百分比,个体价值平均值越高,相同价值越多,价值越低,他们就越不平衡。

有没有人这样做过?

以下是以下示例的PHP转换。出于某种原因,它没有以4,4,4,4为例生成1.0。

$arrayChoices = array(4,4,4,4);

foreach($arrayChoices as $p)
    $sum += $p;

print "sum: ".$sum."<br>";

$pArray = array();

foreach($arrayChoices as $rec)
{
    print "p vector value: ".$rec." ".$rec / $sum."\n<br>";
    array_push($pArray,$rec / $sum);
}   
$total = 0;

foreach($pArray as $p)
    if($p > 0)
        $total = $total - $p*log($p,2);

print "total = $total <br>";

print round($total / log(count($pArray),2) *100);

提前致谢!

2 个答案:

答案 0 :(得分:2)

一个简单的,如果相当幼稚的方案,是将观察结果与完全均匀分布之间的绝对差异相加

red    = abs(4 - 7/4) = 9/4
blue   = abs(0 - 7/4) = 7/4
orange = abs(2 - 7/4) = 1/4
purple = abs(1 - 7/4) = 3/4

总共5个 完全均匀的点差将得分为零,您必须将其映射到100% 假设您在n类别中有c个项目,那么完全不均匀的点差将会得分

(c-1)*n/c + 1*(n-n/c) = 2*(n-n/c)

你应该映射到0%。对于得分d,您可以使用线性转换

100% * (1 - d / (2*(n-n/c)))

对于您的示例,这将导致

100% * (1 - 5 / (2*(7-7/4))) = 100% * (1 - 10/21) ~ 52%

更好(尽管更复杂)是Kolmogorov–Smirnov statistic,您可以使用它来对一组观测值具有某些潜在概率分布的概率进行数学上严格的陈述。

答案 1 :(得分:1)

一种可能性是将您的衡量标准建立在entropy上。均匀分布具有最大熵,因此您可以按如下方式创建度量:

1)将你的计数向量转换为P,一个比例向量     (概率)。

2)计算你的矢量的熵函数H(P)     概率P

3)计算相等向量的熵函数H(U)     与P长度相同的概率。 (事实证明     是H(U) = -log(1.0 / length(P)),所以你实际上并没有     需要创建U作为向量。)

4)您的多样性衡量标准为100 * H(P) / H(U)

任何一组相等的计数都会产生100的多样性。当我将此应用于您的(4,0,2,1)情况时,多样性为68.94。除了一个具有0计数的元素之外的任何向量都具有分集0。

附录

现在有了源代码!我在Ruby中实现了它。

def relative_entropy(v)
  # Sum all the values in the vector v, convert to decimal
  # so we won't have integer division below...
  sum = v.inject(:+).to_f

  # Divide each value in v by sum, store in new array p
  pvals = v.map{|value| value / sum}

  # Build a running total by calculating the entropy contribution for
  # each p.  Entropy is zero if p is zero, in which case total is unchanged.
  # Finally, scale by the entropy equivalent of all proportions being equal.
  pvals.inject(0){|total,p| p > 0 ? (total - p*Math.log2(p)) : total} / Math.log2(pvals.length)
end

# Scale these by 100 to turn into a percentage-like measure
relative_entropy([4,4,4,4])     # => 1.0
relative_entropy([4,0,2,1])     # => 0.6893917467430877
relative_entropy([16,0,0,0])    # => 0.0