var PiD2 = pi() / 2
在 PHP 中不能这样做。只能把简单的常量值赋给实例变量。希望在 PHP5 中会解决这个缺陷。
请注意 清单 1中的代码并未定义实例变量 — 这是因为在 javascript 版本中,它们是动态赋予的值。
清单 1. 实现概率函数
<?php // Distribution.php // Copyright John Pezullo // Released under same terms as PHP. // PHP Port and OO'fying by Paul Meagher class Distribution { function doCommonMath($q, $i, $j, $b) { $zz = 1; $z = $zz; $k = $i; while($k <= $j) { $zz = $zz * $q * $k / ($k - $b); $z = $z + $zz; $k = $k + 2; } return $z; } function getStudentT($t, $df) { $t = abs($t); $w = $t / sqrt($df); $th = atan($w); if ($df == 1) { return 1 - $th / (pi() / 2); } $sth = sin($th); $cth = cos($th); if( ($df % 2) ==1 ) { return 1 - ($th + $sth * $cth * $this->doCommonMath($cth * $cth, 2, $df - 3, -1)) / (pi()/2); } else { return 1 - $sth * $this->doCommonMath($cth * $cth, 1, $df - 3, -1); } } function getInverseStudentT($p, $df) { $v = 0.5; $dv = 0.5; $t = 0; while($dv > 1e-6) { $t = (1 / $v) - 1; $dv = $dv / 2; if ( $this->getStudentT($t, $df) > $p) { $v = $v - $dv; } else { $v = $v + $dv; } } return $t; } function getFisherF($f, $n1, $n2) { // implemented but not shown } function getInverseFisherF($p, $n1, $n2) { // implemented but not shown } } ?> 输出方法
既然您已经用 PHP 实现了概率函数,那么开发基于 PHP 的数据研究工具剩下的唯一难题就是设计用于显示分析结果的方法。
简单的解决方案是根据需要将所有实例变量的值都显示到屏幕上。在第一篇文章中,当显示燃耗研究(Burnout Study)的线性方程、 T值和 T 概率时,我就是这么做的。能根据特定目的而访问特定值是很有帮助的, SimpleLinearRegression 支持此类用法。
然而,另一种用于输出结果的方法是将输出的各部分系统化地进行分组。如果研究用于回归分析的主要统计软件包的输出,就会发现它们往往是用同样的方式对输出进行分组的。它们往往有 摘要表(Summary Table)、 偏离值分析(Analysis Of Variance)表、 参数估计值(Parameter Estimate)表和 R 值(R Value)。类似地,我创建了一些输出方法,名称如下:
- showSummaryTable()
- showAnalysisOfVariance()
- showParameterEstimates()
- showRValues() 我还有一个用于显示线性预测公式的方法( getFormula() )。许多统计软件包不输出公式,而是希望用户根据上述方法的输出构造公式。部分是由于您最后用来对数据建模的公式的最终形式可能由于下列原因而与缺省公式不同:
- Y轴截距没有有意义的解释,或者
- 输入值可能是经过转换的,而您可能需要取消对它们的转换以获取最终的解释。
所有这些方法都假定输出媒介是网页。考虑到您有可能希望用非网页的其它媒介输出这些汇总值,所以我决定将这些输出方法包装在一个继承了 SimpleLinearRegression 类的类中。清单 2中的代码旨在演示输出类的通用逻辑。为了使通用逻辑更突出,所以除去了实现各种 show方法的代码。
清单 2. 演示输出类的通用逻辑
<?php // HTML.php // Copyright 2003, Paul Meagher // Distributed under GPL include_once "slr/SimpleLinearRegression.php"; class SimpleLinearRegressionHTML extends SimpleLinearRegression { function SimpleLinearRegressionHTML($X, $Y, $conf_int) { SimpleLinearRegression::SimpleLinearRegression($X, $Y, $conf_int); } function showTableSummary($x_name, $y_name) { } function showAnalysisOfVariance() { } function showParameterEstimates() { } function showFormula($x_name, $y_name) { } function showRValues() {} } ?>
这个类的构造函数只是 SimpleLinearRegression 类构造函数的包装器。这意味着如果您想显示 SimpleLinearRegression 分析的 HTML 输出,则应该实例化 SimpleLinearRegressionHTML 类,而不是直接实例化 SimpleLinearRegression 类。其优点是不会有许多未使用的方法充斥 SimpleLinearRegression 类,并且可以更自由地定义用于其它输出媒介的类(也许会对不同媒介类型实现同一 API)。
图形输出
迄今为止,您已经实现的输出方法都以 HTML 格式显示汇总值。它也适合于用 GIF、JPEG 或 PNG 格式显示这些数据的分布图(scatter plot)或线图(line plot)。
与其亲自编写生成线图和分布图的代码,我认为最好使用名为 JpGraph的基于 PHP 的图形库。JpGraph 正由 Johan Persson 积极开发,其 项目网站这样描述它:
无论是对于只有最少代码的“以快捷但不恰当方式获得的”图形,还是对于需要非常细粒度控制的复杂专业图形,JpGraph 都可以使它们的绘制变得简单。JpGraph 同样适用于科学和商业类型的图形。
JpGraph 分发版中包含大量可以根据特定需求进行定制的示例脚本。将 JpGraph 用于数据研究工具非常简单,只需找到功能与我的需求类似的示例脚本,然后对该脚本进行改写以满足我的特定需求即可。
清单 3中的脚本是从样本数据研究工具( explore.php)中抽取的,它演示了如何调用该库以及如何将来自于 SimpleLinearRegression 分析的数据填入 Line 和 Scatter 类。这段代码中的注释是 Johan Persson 编写的(JPGraph 代码库的文档化工作做得很好)。
清单 3. 来自于样本数据研究工具 explore.php 的函数的详细内容
<?php // Snippet extracted from explore.php script include ("jpgraph/jpgraph.php"); include ("jpgraph/jpgraph_scatter.php"); include ("jpgraph/jpgraph_line.php"); // Create the graph $graph = new Graph(300,200,'auto'); $graph->SetScale("linlin"); // Setup title $graph->title->Set("$title"); $graph->img->SetMargin(50,20,20,40); $graph->xaxis->SetTitle("$x_name","center"); $graph->yaxis->SetTitleMargin(30); $graph->yaxis->title->Set("$y_name"); $graph->title->SetFont(FF_FONT1,FS_BOLD); // make sure that the X-axis is always at the // bottom at the plot and not just at Y=0 which is // the default position $graph->xaxis->SetPos('min'); // Create the scatter plot with some nice colors $sp1 = new ScatterPlot($slr->Y, $slr->X); $sp1->mark->SetType(MARK_FILLEDCIRCLE); $sp1->mark->SetFillColor("red"); $sp1->SetColor("blue"); $sp1->SetWeight(3); $sp1->mark->SetWidth(4); // Create the regression line $lplot = new LinePlot($slr->PredictedY, $slr->X); $lplot->SetWeight(2); $lplot->SetColor('navy'); // Add the pltos to the line $graph->Add($sp1); $graph->Add($lplot); // ... and stroke $graph_name = "temp/test.png"; $graph->Stroke($graph_name); ?> <img src='<?php echo $graph_name ?>' vspace='15'> ?> 数据研究脚本
该数据研究工具由单个脚本( explore.php)构成,该脚本调用 SimpleLinearRegressionHTML 类和 JpGraph 库的方法。
该脚本使用了简单的处理逻辑。该脚本的第一部分对所提交的表单数据执行基本验证。如果这些表单数据通过验证,则执行该脚本的第二部分。
该脚本的第二部分所包含的代码用于分析数据,并以 HTML 和图形格式显示汇总结果。 清单 4中显示了 explore.php脚本的基本结构:
清单 4. explore.php 的结构
<?php // explore.php if (!empty($x_values)) { $X = explode(",", $x_values); $numX = count($X); } if (!empty($y_values)) { $Y = explode(",", $y_values); $numY = count($Y); } // display entry data entry form if variables not set if ( (empty($title)) OR (empty($x_name)) OR (empty($x_values)) OR (empty($y_name)) OR (empty($conf_int)) OR (empty($y_values)) OR ($numX != $numY) ) { // Omitted code for displaying entry form } else { include_once "slr/SimpleLinearRegressionHTML.php"; $slr = new SimpleLinearRegressionHTML($X, $Y, $conf_int); echo "<h2>$title</h2>"; $slr->showTableSummary($x_name, $y_name); echo "<br><br>"; $slr->showAnalysisOfVariance(); echo "<br><br>"; $slr->showParameterEstimates($x_name, $y_name); echo "<br>"; $slr->showFormula($x_name, $y_name); echo "<br><br>"; $slr->showRValues($x_name, $y_name); echo "<br>"; include ("jpgraph/jpgraph.php"); include ("jpgraph/jpgraph_scatter.php"); include ("jpgraph/jpgraph_line.php"); // The code for displaying the graphics is inline in the // explore.php script. The code for these two line plots // finishes off the script: // Omitted code for displaying scatter plus line plot // Omitted code for displaying residuals plot } ?> 火灾损失研究
为了演示如何使用数据研究工具,我将使用来自假想的火灾损失研究的数据。这个研究将主要住宅区火灾损失的金额与它们到最近消防站的距离关联起来。例如,出于确定保险费的目的,保险公司会对这种关系的研究感兴趣。
该研究的数据如 图 1中的输入屏幕所示。
图 1. 显示研究数据的输入屏幕
数据被提交之后,会对它进行分析,并显示这些分析的结果。第一个显示的结果集是 Table Summary,如 图 2所示。
图 2. Table Summary 是所显示的第一个结果集
Table Summary 以表格形式显示了输入数据和其它列,这些列指出了对应于观测值 X的预测值 Y、 Y值的预测值和观测值之间的差以及预测 Y值置信区间的下限和上限。
图 3显示了 Table Summary 之后的三个高级别数据汇总表。
图 3. 显示了 Table Summary 之后的三个高级别数据汇总表
Analysis of Variance表显示了如何将 Y值的偏离值归为两个主要的偏离值来源,由模型解释的方差(请看 Model 行)和模型不能解释的方差(请看 Error 行)。较大的 F值意味着该线性模型捕获了 Y测量值中的大多数偏离值。这个表在多次回归环境中更有用,在那里每个独立变量都在表中占有一行。
Parameter Estimates表显示了估算的 Y 轴截距(Intercept)和斜率(Slope)。每行都包括一个 T值以及观测到极限 T值的概率(请看 Prob > T 列)。斜率的 Prob > T可用于否决线性模型。
如果 T值的概率大于 0.05(或者是类似的小概率),那么您可以否决该无效假设,因为随机观测到极限值的可能性很小。否则您就必须使用该无效假设。
在火灾损失研究中,随机获得大小为 12.57 的 T值的概率小于 0.00000。这意味着对于与该研究中观测到的 X值区间相对应的 Y值而言,线性模型是有用的预测器(比 Y值的平均值更好)。
最终报告显示了相关性系数或 R 值。可以用它们来评估线性模型与数据的吻合程度。高的 R 值表明吻合良好。
每个汇总报告对有关线性模型和数据之间关系的各种分析问题提供了答案。请查阅 Hamilton、Neter 或 Pedhauzeur 编写的教科书,以了解更高级的回归分析处理。
要显示的最终报告元素是数据的分布图和线图,如 图 4所示。
图 4. 最终报告元素 — 分布图和线图
大多数人都熟悉线图(如本系列中的第一幅图)的说明,因此我将不对此进行注释,只想说 JPGraph 库可以产生用于 Web 的高质量科学图表。当您输入分布或直线数据时,它也做得很好。
第二幅图将残差(观测的 Y、预测的 Y)与您预测的 Y值关联起来。这是 研究性数据分析(Exploratory Data Analysis,EDA)的倡导者所使用的图形示例,用以帮助将分析人员对数据中的模式的检测和理解能力提到最高程度。行家可以使用这幅图回答关于下列方面的问题: