mineria / php-r
Hack R PHP 库
Requires
- php: >=5.3.9
This package is not auto-updated.
Last update: 2024-09-29 04:43:08 UTC
README
PHPR (或 php-r) 是一个库,它提供了在 PHP 中运行 R 脚本的能力。Composer 包: kachkaev/php-r。
可选地,该库以 包的形式 可供 Symfony2 用户使用。
该想法基于调用 R 的命令行版本并与之外部进程交换消息。由于库的架构支持,可以轻松实现与基于服务器的 R 实现的集成。
既可以批量运行所有 R 代码,也可以与 R 解释器交互式地交换命令。
用法
选项 1: 批量运行所有 R 代码
use Kachkaev\PHPR\RCore; use Kachkaev\PHPR\Engine\CommandLineREngine; $r = new RCore(new CommandLineREngine('/path/to/R')); $result = $r->run(<<<EOF x = 1 y = 2 x + y x + z x - y EOF ); echo $result;
PHP 输出
> x = 1
> y = 2
> x + y
[1] 3
> x + z
Error: object 'z' not found
> x - y
[1] -1
方法 run() 总是在 R 变量的干净作用域内调用,即以下用法将导致 R 错误
echo $r->run("x = 100") echo "\n=====\n" echo $r->run("x * x")
PHP 输出
> x = 100
=====
> x * x
Error: object 'x' not found
选项 2: 交互式交换数据
为了与单个 R 进程交互式地交换命令,应使用另一种方法
use Kachkaev\PHPR\RCore; use Kachkaev\PHPR\Engine\CommandLineREngine; $r = new RCore(new CommandLineREngine('/path/to/R')); $rProcess = $r->createInteractiveProcess(); $rProcess->start(); $rProcess->write('x = 100'); // Do something else $rProcess->write('x * x'); echo $rProcess->getAllResult();
PHP 输出
> x = 100
> x * x
[1] 10000
该过程是同步的,即如果发送到 write() 的 R 代码涉及一些复杂计算,PHP 将等待它们完成。
可以在一个 write() 中传递多个命令给 R;它们也可以是多行的
$rProcess->write(<<<EOF x = 1 y = 10 + (x + x / 2) z = 42 EOF );
严格来说,必须保持命令完整。以下示例将导致关键错误,并且 R 进程将被终止。
$rProcess->write('x = 1 + ('); // IncompleteRCommandException
每个 R 命令单独访问输入/输出/错误
为了避免手动拆分 R 输入、输出和错误的混合,可以单独访问脚本执行的结果
$rProcess = $r->createInteractiveProcess(); $rProcess->start(); $rProcess->write(<<<EOF x = 1 y = 2 x y EOF ); $rProcess->write(<<<EOF x + 41 x + xxx x + y EOF ); echo $rProcess->getLastWriteInput(); // x + 41 // x + xxx // x + y echo $rProcess->getLastWriteOutput(); // 42 // // [1] 3 echo $rProcess->hasLastWriteErrors(); // true echo $rProcess->getLastWriteErrorCount(); // 1 $errors = $rProcess->getLastWriteErrors(); echo $errors[0]->getErrorMessage() // object 'xxx' not found echo $errors[0]->getCommand() // x + xxx $rProcess->getAllInput(); $rProcess->getAllOutput(); $rProcess->hasErrors(); $rProcess->getErrorCount(); $rProcess->getErrors();
将 true 传递到 get(LastWrite|All)Input/get(LastWrite|All)Output/get(LastWrite|All)Result 将字符串拆分为数组,其中每个元素对应一个单个命令
$rProcess = $r->createInteractiveProcess(); $rProcess->start(); $rProcess->write(<<<EOF x = 1 + 1 y x EOF ); $inputAsArray = $rProcess->getAllInput(true); // ['x ={newline}1 + 1', 'y', 'x'] $outputAsArray = $rProcess->getAllOutput(true); // ['', null, '2'] $resultAsArray = $rProcess->getAllResult(true); // [ // ['x ={newline}1 + 1', '', null], // ['y', null, 'Error: object \'y\' not found'], // ['x', '2', null] // ]
对 R 错误的敏感性
如果需要确保一系列 R 命令没有错误地运行,并且每次在 write() 后调用 hasLastWriteErrors() 都是不合理的,则可以将进程设置为对错误敏感。在 write() 上将引发 RErrorsException
$rProcess->setErrorSensitive(true); $rProcess->write('x = 1 + missingVariable'); // RErrorsException
这等同于
$rProcess->setErrorSensitive(false); $rProcess->write('x = 1 + missingVariable'); if ($rProcess->hasLastWriteErrors()) { throw new RErrorsException($rProcess->getLastWriteInput(true), $rProcess->getLastWriteOutput(true), $rProcess->getLastWriteErrors()); }
R 相关的错误和抛出的异常不是关键的;在它们发生之后,仍然可以使用相同的 R 进程。如果最后一个输入包含多个命令,并且其中一些导致错误,则 RErrorsException 将包含完整的列表。在任何情况下,都将尝试通过 R 解释器传递给 write() 的所有命令。
$allErrors = $rErrorsException->getErrors(); if (count ($allErrors) > 1) { $secondError = $allErrors[1]; echo $secondError->getErrorMessage(); }
解析 R 输出
为了简化 R 输出的解析,可以使用 ROutputParser
use Kachkaev\PHPR\ROutputParser; $rOutputParser = new ROutputParser(); $rProcess->write('21 + 21'); var_dump($rProcess->getLastWriteOutput()); // string(6) "[1] 42" var_dump($rOutputParser->singleNumber($rProcess->getLastWriteOutput())); // int(42)
有关更多信息,请参阅类中的 PHPdoc 注释。
许可
MIT。见 LICENSE。
php-r
安装 Composer