kachkaev / php-r
提供从PHP运行R脚本的能力
Requires
- php: >=5.3.9
This package is not auto-updated.
Last update: 2020-11-29 00:09:16 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
将包含完整的列表。在任何情况下,都会尝试将传递给 write()
的所有命令交给R解释器。
$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。