博客园  :: 首页  :: 新随笔  :: 订阅 订阅  :: 管理

PHP 相关性系数计算

Posted on 2019-07-17 11:07  PHP-张工  阅读(990)  评论(0编辑  收藏  举报

相关系数公式

参考:https://baike.baidu.com/item/相关系数

PHP 实现代码

public static function calc($list)
{
    $cv = [];
    $X = [];
    $Y = [];
    
    foreach ($list as $r)
    {
        if (count($r) != 2)
        {
            continue;
        }
        
        $X[] = floatval($r[0]);
        $Y[] = floatval($r[1]);
    }

    $xavg = array_sum($X)/count($X); // X 平均值
    $yavg = array_sum($Y)/count($Y); // Y 平均值
    $XMD = [];         // X 离均差
    $YMD = [];         // Y 离均差
    $mdcross_sum = 0;       // X,Y 离均差交乘积和
    $xdif_square_sum = 0;   // X 离均差平方和
    $count = count($X);
    for ($i=0; $i<$count; $i++)
    {
        $xdif = (float)$X[$i]-$xavg; // X 离均差
        $ydif = (float)$Y[$i]-$yavg; // Y 离均差
        $XMD[$i] = $xdif;
        $YMD[$i] = $ydif;
        $mdcross_sum += $xdif*$ydif;       // X,Y 离均差交乘积和
        $xdif_square_sum += pow($xdif, 2); // X 离均差平方和
    }

    if ($xdif_square_sum == 0)
    {
        $b = 0;
        $a = 0;
    }
    else
    {
        $b = round($mdcross_sum/$xdif_square_sum, 2);   // 计算斜率 b
        $a = round($yavg-$b*$xavg, 2);                  // 计算常数项 a
    }

    /*
    $str = '';
    $str .= "X = ".join(", ",$X)."<br>";
    $str .= "Y = ".join(", ",$Y)."<br>";
    $str .= "常数项 a = ".$a."<br>";
    $str .= "斜率 b = ".$b."<br>";
    $str .= "线性回归方程式 Y = ".$a." + (".$b.")X<br>";
    $str .= "X 平均值 = ".$xavg."<br>";
    $str .= "Y 平均值 = ".$yavg."<br>";
    $str .= "X 离均差 = ".join(", ",$XMD)."<br>";
    $str .= "Y 离均差 = ".join(", ",$YMD)."<br>";
    $str .= "X,Y 离均差交乘积和 = ".$mdcross_sum."<br>";
    $str .= "X 离均差平方和 = ".$xdif_square_sum."<br>";
    
    SysLog::add($str, 'debug');
    */

    $cv['a'] = $a;
    $cv['b'] = $b;

    // 计算相关系数
    $cv_up = 0;
    $cv_down_x = 0;
    $cv_down_y = 0;
    for ($i=0; $i<$count; $i++)
    {
        $cv_up += ($X[$i]-$xavg) * ($Y[$i]-$yavg);
        $cv_down_x += pow($X[$i]-$xavg, 2);
        $cv_down_y += pow($Y[$i]-$yavg, 2);
    }

    if ($cv_down_x * $cv_down_y == 0)
    {
        $cv['cv'] = 0;
    }
    else
    {
        $cv['cv'] = round($cv_up / sqrt($cv_down_x * $cv_down_y), 2);
    }

    return $cv;
}