需要计算分配百分比

问题描述 投票:0回答:2

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

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);

提前致谢!

php math average distribution
2个回答
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 统计量,您可以使用它对一组观测值具有某些给定的潜在概率分布的概率做出数学上严格的陈述。


1
投票

一种可能性是将你的测量基于。 均匀分布具有最大熵,因此您可以按如下方式创建度量:

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
© www.soinside.com 2019 - 2024. All rights reserved.