日々のつれづれ

不惑をむかえ戸惑いを隠せない男性の独り言

ファイルの書き出し

Rで関数が使えるようになると、結果をファイルに書き出したり、外部からファイルを持ってきたりしたくなるはず。

書き出す目的は様々ですが、誰かにファイルを渡すために書き出すことが多いような気がする。
そして、受け取った相手はエクセルを使っていたりする。
で、「エクセルで視認性が高い書き出しって何?」ってことになる。
エクセルのようなスプレッドシート型で書き出すためには、write.table関数を使うことになる。
write.table関数は引数sep, col.names, row.namesに気をつければ、何とかなる。

  • matrix オブジェクトの書き出し
> (x <- matrix(1:12,ncol=3,dimnames=list(1:4,c("col1","col2","col3"))))
  col1 col2 col3
1    1    5    9
2    2    6   10
3    3    7   11
4    4    8   12
> write.table(x,file="matrix1.txt",sep="\t")
> write.table(x,file="matrix2.txt",sep="\t",row.names=FALSE)
> write.table(x,file="matrix3.txt",sep="\t",col.names=NA)
> write.table(x,file="matrix4.txt",sep=",",col.names=NA)

引数を変えた4 つのファイルを確認して下さい。

    • matrix1.txt は行列が崩れていると思います。一つ目の行名が列名にずれ込んでいて、きっとエクセルユーザーから、「カラムの名前が間違ってるよ〜、手で直さないといけないよ、Rって使えないな〜」って言わるはず。
    • matrix2.txtはエクセルで視認性が高いと思います。rowname=FALSEは行名を消してくれるのでcol.namesがずれ込むことがありません。エクセルユーザーからもクレームもないはず。
    • matrix3.txtはケース・バイ・ケースですね。row.anmesが残って、col.namesも残っている。そして、エクセルで言う所の「A1」セルが空欄になっていてmatrix1.txtのようなずれ込みもない。
    • matrix4.txt は本質的にmatrix3.txtと同じです。違いは「区切り文字」。エクセルで出力するところの「タブ区切りテキスト」と「CSVファイル」の違いです。これもケース・バイ・ケースですね。

経験的には、

    • row.namesが数値ならmatrix2.txtの受けが良い

これは数値がA列にあると、「この連番は何?エクセルの列番号と一緒だよね?いらないよ。」っていわれるから。

    • row.namesが文字列ならmatrix3.txtの受けがいい。

下のような場合で、「row1とrow2の値」と行と列のクロスするセルが意味を持つ。row.namesがなくなっちゃうと各列の数値が何を意味するか分からなる(いわずもがなですね)。

(x <- matrix(1:12, ncol=3, dimnames=list(c("row1","row2","row3","row4"),c("col1","col2","col3"))))
write.table(x,file="matrix3.txt",sep="\t",col.names=NA)
    • csvは意外と受けが悪い。

これは、次のdata.frameのときにありがちなんですが、文字列行にコンマがやたら入っていることがある。
こういったとき、csvで出力してしまうとエクセルで勝手にセルが分離されて、「なんだよ〜、データがずれてるじゃないか〜Rって使えないな〜」ってことになるから。

  • data.frame オブジェクトの書き出し

data.frame の出力はcolumn 属性がnumericやintegerなら数字、characterやfactorなら文字で出力される。文字は"ダブルクオート"で挟まれます(引数quoteで制御できます)。

> (x <- data.frame("num"=1:3,"char"=I(c("a","b","c")), "factor"=c("A","B","C"), row.names=c("row1","row2","row3")))
     num char factor
row1   1    a      A
row2   2    b      B
row3   3    c      C
> write.table(x,file="data.frame1.txt",sep="\t",col.names=NA)
  • エクセルにwrite.tableの出力をエクセルファイルと思い込ませる

write.tableの出力はどちらもフラットファイルなので、エクセルで読み込むときはインポートすることになります。
でも、できればアイコンダブルクリックでエクセルで開きたいはず。
で、どうやらエクセルは「タブ区切りテキスト」をエクセルファイルと思うらしく、拡張子をごまかせばいいらしい。

> x <- data.frame("num"=1:3,"char"=I(c("a","b","c")), "factor"=c("A","B","C"), row.names=c("row1","row2","row3"))
> write.table(x,file="data.frame1.xls",sep="\t",col.names=NA)

引数fileのファイル名で拡張子を".xls"にして、sep="\t"にすればエクセルは騙されてくれるみたいです。
(エクセル2003はアラートが出ると言われたのですが、私は使ったことがないので未確認。)

余談ですが、少しの不具合で「Rってな〜」って言わしめるのだから、エクセルってすごいと思う。