使用对数刻度缩放和标准化数据

时间:2017-10-22 11:16:32

标签: php normalize

我想在我的网站上为用户创建排名系统。排名将由许多因素决定,例如他们成为会员的时间,他们创建了多少帖子等。每个数据项也除以我确定的“权重”,因此它更具代表性实际的用户活动 - 我不希望1个帖子与成员一样重要。称重后,将所有统计数据加在一起。

然后,我必须对总数进行标准化,以便将它们分配到1到20的等级,因为一些成员只有几个活动点,而一些退伍军人有数千个积分。我通过规范化数据并使用此函数将其缩小到1-20等级范围来实现此目的:

function normalize($userTotal, $minOriginalRange, $maxOriginalRange, $minNewRange, $maxNewRange){
    return $minNewRange + ((($maxNewRange - $minNewRange) * ($originalValue - $minOriginalRange)) / ($maxOriginalRange - $minOriginalRange));
}

这通常被称为:     normalize(getUserTotal(),0,getHighestTotalOfAllMembers(),1,20);

所以我得到了这个结果,关键是等级和价值是获得该等级的成员数量:

Array
(
    [1] => 7418
    [2] => 1918
    [3] => 289
    [4] => 102
    [5] => 62
    [6] => 28
    [7] => 21
    [8] => 14
    [9] => 1
    [10] => 8
    [11] => 6
    [12] => 5
    [13] => 1
    [14] => 1
    [17] => 1
    [20] => 1
)

正如你所看到的,有很多用户排名很低,很少有人被分配到中高级别。我想通过计算使用对数刻度分配的等级来解决这个问题,这样就可以很容易地爬上较低等级的等级,并且越高越好。这样它应该更均匀地分布,更多的用户将在中间排名。

我不知道如何处理这个问题,但是我从来没有使用过对数标度,而且总是在我的代码中使用简单的算法。

1 个答案:

答案 0 :(得分:0)

您将使用php math logarithm函数并将其映射到最终数组,例如:

function logfunction($v){
return round(log1p($v),2);  
}

$simple_array = [7418, 1918, 289, 102, 62, 28, 21, 14, 1, 8, 6, 5, 1, 1, 1];
$logarithmic_array = array_map(logfunction, $simple_array);
print_r($logarithmic_array);

在上面,我使用了log1p()函数,即使数值接近于零,也会以一种准确的方式计算出log(1 + number)的计算结果(参见:http://php.net/manual/en/function.log1p.php)。然后,为了便于阅读,我将结果舍入到2位小数。生成的$logarithmic_array输出为:

   Array
     (
         [0] => 8.91
         [1] => 7.56
         [2] => 5.67
         [3] => 4.63
         [4] => 4.14
         [5] => 3.37
         [6] => 3.09
         [7] => 2.71
         [8] => 0.69
         [9] => 2.2
        [10] => 1.95
        [11] => 1.79
        [12] => 0.69
        [13] => 0.69
        [14] => 0.69
    )