Rめも: scanの入力先変更、コマンドライン引数、pngエラー

Rコマンドそのものをフィルタとして使う勝手はよくないようだ。 パイプの先でRを使うより、処理すべきものを引数リストで渡して Rで能動的に処理させた方がやりやすい感じ。

scanの入力先

最初、標準入力を取らせようと思って

scan("", what=list(a="", b=0))

みたいにして、Rscript hoge.R < file したけどだめだった。 scan のファイル名に /dev/stdin もだめ。 NetBSDはうまくいくけどSolarisでNG。

Rで ?connections したらだいたい分かった。なるほど。 標準入力を取らせたいなら

fd <- pipe("cat")
scan(file=fd, ...)
close(fd)

みたいな感じでOK。外部コマンドを読んで結果をとるならpipe() でよい感じ。これを使おう。

コマンドライン引数

ということでシェルスクリプトでループしてその内部で Rへパイプで標準入力渡しより、先に複数の引数を渡してRでループさせた 方が楽。

コマンドライン引数は commandArgs() で取れて、 commandArgs(T)--args より後ろのもの(つまり欲しいものだけ)取り出せる。

png吐き出し w/o X11

$DISPLAY がセットされてないと、というかX11()環境がないと PNGもJPEGも吐き出せないとな! バックグラウンド動作させられないじゃないか! RjpWiki R-FAQ 7.21 か。Xvfb を使えとあるが、うちの Solaris10/sparc でうまく行かなかった。けどまあ、どっか自由に使えるDISPLAYがあれば いいってことで、幸いXvncを導入済みなのでそれを使った。

Xvnc :xxxx
export DISPLAY=:xxxx

行けた。でも起動しとくことを忘れそうだな。

まとめると

シェルスクリプト屋の頭でこんな感じのことをやろうとしていた。

for i in "$@"; do
  grep hoge $i/* | sort | uniq -c | Rscript hogehoge.R
done

Rで標準入力を受けて文字列処理をごにょごにょやるのもなんだし、 R自体の起動も重いので次のように変えた。

DISPLAY=:xxxx Rscript hogehoge2.R "$@"

hogehoge2.Rはこんな風。

#!/usr/bin/env Rscript
for (i in commandArgs(T)) {
  png(file=sprintf("output/%i.png", i))
  fd=pipe(sprintf("grep hoge %s/* | sort | uniq -c"))
  x <- scan(file=fd, what=list(count=0, item=""))
  close(fd)
  # グラフ作成いろいろ
  dev.off()
done