Использование R в Perl

По-настоящему хорошие инструменты всегда специализированы. В реальности же часто требуется объединение лучшего, что есть в обоих языках - огромная вычислительная мощь R и удобство Perl. Опишу свой опыт по интеграции R в Perl

Задача использования R в Perl возникла при написании простейшего скрипта для подсчета встречающихся слов заданной длины. При всей банальности задачи выяснилось, что программа compseq из EMBOSS не умеет определять уровень значимости(!!), показывая всего лишь отношение наблюдаемых частот к ожидаемым. Разумно использовать биномиальный тест из R и тем самым на порядок переплюнуть EMBOSS по функциональности :).

Похоже, что вариантов интеграции R и Perl не так много - есть пакет RSPerl (http://www.omegahat.org/RSPerl/), который работает только в Unix (что для меня было неприемлимо) и модуль Statistics::R из CPAN. Последний и был использован. Сразу оговорюсь, что есть много недостатков, но зато хоть как-то работает.

Вот пример, который у меня выполняется (естественно, после инсталляции пакета из CPAN):

 

use Statistics::R ;

my $R = Statistics::R->new( r_bin => "c:/Programs/R-2.6.0/bin/r.exe" );
$R->startR ;

#NB: похоже здесь изменяется рабочая директория

# вся графика должна быть послана за один вызов send()

$str = q`
png("rtemp.png");
plot(c(1, 5, 10,15), type = "l");
dev.off();
`;

$R->send($str);

$R->send('x <- matrix(c(12, 5, 7, 7), ncol = 2);');
$R->send(' print(chisq.test(x)$p.value);');
my $ret = $R->read ;

$R->send('print(getwd());');
my $ret2 = $R->read ;

#here all files are deleted!!!
$R->stopR() ;

print "bye";

 

Итак, замеченные недостатки (на Win XP SP3)

  1. все работает совсем не быстро
  2. после вызова startR изменяется рабочая директория. В каталоге R создается подкаталог Statistics-R, где добавляется подкаталог output. Там выводится масса скрытых файлов с промежуточными результатами.
  3. После вызова stopR() все эти файлы стираются, поэтому если они нужны то нужно их до этого оттуда скопировать.
  4. Вся графика (перенаправляемая в файл) должна быть выведена за один вызов send(). В противном случае будет пустой файл (не знаю почему, но это так)
  5. Иногда вызов проваливается по неведомой причине, поэтому получив в результате работы read() строку с сообщением об ошибке предусмотрите в коде перезапуск расчета.

Все же, несмотря на все эти недостатки – работает. Скрипт успешно считает значимость различия между наблюдаемой встречаемостью слова и ожидаемой. EMBOSS курит на лестнице :)

Если вы знаете другой способ интеграции Perl и R (кроме COM) напишите, плиз. На вопросы в комментах – попробую ответить по мере сил.