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ってな〜」って言わしめるのだから、エクセルってすごいと思う。