2014年8月29日金曜日

Rで空のCSVファイルを読み込むとエラーが出てしまう場合の対処方法

例えば、複数のCSVファイルがあって、それをまとめて処理したいとしましょう。

"001.csv"は、

  taro,60
  hanako,100
  ichiro,90
  ...


"002.csv"は

  jiro,50
  keiko,70
  ...


みたいな感じでたくさんのCSVファイルがあって、それぞれを集計したいとか、全部をマージしたいとか、そんな場合。

以下のようなコードで処理しようとするんじゃないでしょうか、

files <- dir(pattern="\\.csv")
 
for(f in files){
  data <- read.csv(f, header=F)
 
  # このあとデータを集計するような処理
}


普通は上記でうまくいくんですが、たまに変なファイルが混じってたりする。

例えば、空のCSVファイルとか。

すると、

 以下にエラー read.table(file = file, header = header, sep = sep, quote = quote,  :
   入力中には利用可能な行がありません


というエラーメッセージが出て、処理が中断してしまいます。

人名と点数のデータみたいなものだと空のファイルなんてのは考えにくいですが、「複数の画像から顔検出して、検出位置の座標をCSVで出力」みたいな場合だと、不検出の場合は空のファイルができあがっている、なんてことはよくあります。

そういう場合の対処方法としては、try関数を使うと便利です。

for(f in files){
  # read.csvでエラーが出たかどうかはresに設定される
  res <- try ( data <- read.csv(f, header=F), silent=T )
 
  if( class(res) != "try-error" ) {
    # エラーが出なかったので、分析処理を続ける
    # ...
  } else {
    # 空のファイルがあったときの処理
    print("空のファイルがあったよ")
  }
}

try関数で囲んでおくと、エラーが出ても止まりません。エラーが出たかどうかは、resに設定されていますので、if文で処理を分けてやればOKですね。

silent=Fに変えると、発生したエラーメッセージを表示させる(処理は継続される)こともできます。




2014年8月28日木曜日

Rでjpeg画像を読み込み、加工する

もともと存在する画像(jpegファイルやpngファイル)を読み込んで、線や図形を書き足したり、文字を書き足したり、そんな感じの加工をRを使って行う方法です。

発想としては、plot関数で用意した作画領域に、rasterImage関数で画像を貼り付けしまえば、そのあとは使い慣れた(?)低水準作図関数でいろいろ落書きができるでしょ、という感じです。

Rでlenaさんの画像を読み込んで、rectで加工したもの
library(jpeg)
lena <- readJPEG("lena.jpg") # あの女性の画像
plot( 0,0, xlim=c(0,512), ylim=c(512,0), type="n", asp=1 )
rasterImage(lena, 0, 512, 512, 0)
rect( 220,200, 360,390, border="cyan" )

plot関数のylimオプションが上下逆になっているのがポイントです。jpeg上での座標の扱いは左上が原点になっているからなんですね。

rasterImage関数には、xleft, ybottom, xright, ytopの順で指定することになっています。つまり、貼り付けたい場所の左下(xleft, ybottom)と右上(xright, ytop)を指定しろということですね。対応する座標は、(0,512)と(512,0)になりますので、

rasterImage(lena, 0, 512, 512, 0)

で、正しく貼り付けられるわけです。

あとは低水準作図関数を駆使して、rect関数で矩形を描くなり、abline関数で線を引くなり、text関数で文字を書き込むなりすればいいんじゃないでしょうか。

で、お気づきだとは思いますが、x軸・y軸とかラベルとかが邪魔ですよね。これについては「余白なし」の設定になるように、plotの前にパラメタ指定しておけばOKです。軸やラベルは作画領域の外に追いやられ、見えなくなります。

余白なしにして、軸やラベルを表示させないようにしたもの

old.par <- par(no.readonly = TRUE) # 現状パラメタの退避
par( plt=c(0,1,0,1) ) # 余白なしの設定

plot( 0,0, xlim=c(0,512), ylim=c(512,0), type="n", asp=1 )
rasterImage(lena, 0, 512, 512, 0)
rect( 220,200, 360,390, border="cyan" )

par(old.par) # パラメタを元に戻す

パラメタの退避・復元は必須ではないんですが、やっておかないと、その後のplotでは軸やラベルが表示されなくなってしまいます。Rで他の作業をするときに困りますよね。(Rを起動しなおせば直りますが)

あとは、できあがった画像をファイルとして出力しましょう。

jpeg("out.jpg", width=512, height=512) # jpegファイルのオープン

old.par <- par(no.readonly = TRUE) # 現状パラメタの退避
par( plt=c(0,1,0,1) ) # 余白なしの設定

plot( 0,0, xlim=c(0,512), ylim=c(512,0), type="n", asp=1 )
rasterImage(lena, 0, 512, 512, 0)
rect( 220,200, 360,390, border="cyan" )

par(old.par) # パラメタを元に戻す

dev.off() # jpegファイルのクローズ

ファイルをオープンしているところのjpeg関数を、png関数に変更すればpngファイルに書き出すこともできます。

できあがったファイルを見てもらえば分かりますが、外周に白枠が追加されてしまっています。

これを消す方法は・・・分かりませんでした。誰か教えてください。