データファイルをRの外側に持ってアクセス
- Rのこんなパッケージシリーズがある。「XxxABEL」(ホームページ)
- その中のGenABELが『ノートでGWAS』の関数群らしい
- それを支えているのがDatABEL
- 巨大な行列形式のデータをRで効率的・高速に扱うための仕組み
- ファイルとして持っている行列形式のテキストファイルを参照させてRの中で行列的にアクセスできるオブジェクト(databelオブジェクト)として持つ機能があり
- Rの中の行列をdatabelオブジェクトとすることもできる。このdatableオブジェクトにする、ということは、バイナリーファイルをコンピュータ上に作成する(作成してR内から値参照する)ということでもある
- バイナリファイルとして(も)存在しているdatableオブジェクトはテキストファイルとして書き出すこともできる
# working directoryをどこか、新たに指定しておこう # install.packages("DatABEL") library(DatABEL) # ふつうに行列を作る matr <- matrix(c(1:12), ncol = 3, nrow = 4) matr[3, 2] <- NA matr # 行・列にラベルを付ける dimnames(matr) <- list(paste("row", 1:4, sep = ""), paste("col", 1:3, sep = "")) matr
> matr col1 col2 col3 row1 1 5 9 row2 2 6 10 row3 3 NA 11 row4 4 8 12
# Working directryに、拡張子が"fv..."なるファイルがあるか、と確認すれば、その答えは、「なし」
list.files(pattern = "*.fv?")
> list.files(pattern = "*.fv?") character(0)
# as()を使って、行列オブジェクトmatrから、databelオブジェクトdat1を作る dat1 <- as(matr,"databel") # matrと同様の値が表示されるが、それ以外にも、行列に関する情報が表示され、行列オブジェクトではないことがわかる # backingfilename に参照しているバイナリファイルが記されている dat1
> dat1 uninames$unique.names = TRUE uninames$unique.rownames = TRUE uninames$unique.colnames = TRUE backingfilename = ./tmp122808 cachesizeMb = 64 number of columns (variables) = 3 number of rows (observations) = 4 usedRowIndex: 1 2 3 4 usedColIndex: 1 2 3 Upper-left 3 columns and 4 rows: col1 col2 col3 row1 1 5 9 row2 2 6 10 row3 3 NaN 11 row4 4 8 12
# ここで、Working directoryのファイルをチェックすると # fvd, fviなる拡張子のファイルができていることがわかる list.files(pattern = "*.fv?")
> list.files(pattern = "*.fv?") [1] "tmp630321.fvd" "tmp630321.fvi"
- これをPCの方で開こうとすると(開くと)、バイナリファイルであることがわかる
# matrix2databel()という関数を使って、datableオブジェクトを作ることもできる # この場合は、コンピュータ側にできるファイルの拡張子以外の部分の名称を指定することができる。その他のオプションもある dat2 <- matrix2databel(matr, filename = "matr", cachesizeMb = 16, type = "UNSIGNED_CHAR", readonly = FALSE) # 作られるdatabelオブジェクトはas()関数での作成の場合と同様で dat2 # また、PC側にfvd,fviなる拡張子のファイルができることも同様 list.files(pattern = "*.fv?")
> dat2 uninames$unique.names = TRUE uninames$unique.rownames = TRUE uninames$unique.colnames = TRUE backingfilename = matr cachesizeMb = 16 number of columns (variables) = 3 number of rows (observations) = 4 usedRowIndex: 1 2 3 4 usedColIndex: 1 2 3 Upper-left 3 columns and 4 rows: col1 col2 col3 row1 1 5 9 row2 2 6 10 row3 3 NaN 11 row4 4 8 12 > list.files(pattern = "*.fv?") [1] "matr.fvd" "matr.fvi" "tmp630321.fvd" "tmp630321.fvi"
# Woking directoryのmatr.fvd, matr.fviを指定して、そこからdatableオブジェクトを作ることもできる dat3 <- databel("matr") dat3 # Rの行列オブジェクトmatrから、コンピュータにテキストファイルmatr.txtを書き出して write.table(matr, "matr.txt", row.names = TRUE, col.names = TRUE, quote = FALSE) # 書き出したテキストファイルからdatabelオブジェクトを作ることもできる # そのときに、対応するバイナリファイルができなくてはならないので、その名称をmatr1.fvd, matr1.fviと指定していることもわかる dat4 <- text2databel("matr.txt", outfile = "matr1", R_matrix = TRUE, type = "UNSIGNED_INT") # datable オブジェクトから別のdatabelオブジェクトを作ることもできて # そのときは、どちらのdatabelオブジェクトも同じバイナリファイルに紐づいていることになる dat4 dat5 <- dat4 # 同様にdatabelオブジェクトを行列的に扱って、行・列を抽出して部分行列に対応するdatableオブジェクトdat6を作ることもできる # この場合も新たにバイナリファイルを作るわけではなく、バイナリファイルに値参照しに行く形式となっている dat6 <- dat1[c("row1", "row3"), c("col1", "col2")] dat6
# datableオブジェクトはPCのファイルシステムと連携しているので、中の値を変えられるか変えられないかに制約がある # 複数のdatableオブジェクトが同一のバイナリファイルを参照していれば、一つを変えると、別も変わる dat1[1, 1] <- 321 dat6
- datableオブジェクトの継承具合と、バイナリファイルの参照関係、値の書き換え可否について、以下のように実行してみる
- datableオブジェクトの表示がうるさいので、backingfilenameと値のみをコピーしてある
# それぞれのbackingfilenameを確認 # ./tmpxxxxとmatr,matr1の3ファイルある > dat1 backingfilename = ./tmp727998 col1 col2 col3 row1 1 5 9 row2 2 6 10 row3 3 NaN 11 row4 4 8 12 > dat1[1,1] backingfilename = ./tmp727998 col1 row1 1 > dat2[1,1] uninames$unique.names = TRUE backingfilename = matr col1 row1 1 > dat3[1,1] backingfilename = matr cachesizeMb = 64 col1 row1 1 > dat4[1,1] backingfilename = matr1 col1 row1 1 > dat5[1,1] backingfilename = matr1 col1 row1 1 > dat6[1,1] backingfilename = ./tmp727998 cachesizeMb = 64 col1 row1 1 # 書き換えが可能なのは、dat1,dat2の2つだけ > dat1[1,1]<-111 > dat2[1,1]<-222 # dat3はmatrに紐づいているが、それに直接、紐づいているdat2とは違って、書き換えられない # その代り、dat2を書き換えるとdat3も書き換わる > dat3[1,1]<-333 Loss of precision / loss of data during conversion from DOUBLE to INT. Futher conversion warnings omitted. Trying to write to the readonly file. 以下にエラー !.Call("assignDoubleMatrix", x@data, newi, newj, as.double(value), : 引数の型が不正です # dat4も書き換えられない # バイナリファイル名としてはmatr1と、独立しているが # 大元がmatr1.txtというPCの世界での「ちゃんとしたファイル」なので、それの書き換えはRの中からはできない # 逆に言えば、テキストファイルとしてPC上に存在しないがdatableオブジェクトの値参照先としておかれているバイナリファイルは、書き換え可能ということ > dat4[1,1]<-444 Trying to write to the readonly file. 以下にエラー !.Call("assignDoubleMatrix", x@data, newi, newj, as.double(value), : 引数の型が不正です # dat5はdat4の子であって、dat4が書き換えられないのだから、書き換えられるわけがない > dat5[1,1]<-555 Trying to write to the readonly file. 以下にエラー !.Call("assignDoubleMatrix", x@data, newi, newj, as.double(value), : 引数の型が不正です # dat6はdat1を継承しているから、dat6の書き換えはできず、dat1の変更がdat6にも及んでいる > dat6[1,1]<-666 Trying to write to the readonly file. 以下にエラー !.Call("assignDoubleMatrix", x@data, newi, newj, as.double(value), : 引数の型が不正です > dat1[1,1] backingfilename = ./tmp727998 col1 row1 111 > dat2[1,1] backingfilename = matr col1 row1 222 > dat3[1,1] backingfilename = matr col1 row1 222 > dat4[1,1] backingfilename = matr1 col1 row1 1 > dat5[1,1] backingfilename = matr1 col1 row1 1 > dat6[1,1] backingfilename = ./tmp727998 col1 row1 111
- 上で見てきたのは、datableオブジェクトをreadonly指定していたから
- それを解除すると、継承して作ったdatableオブジェクトの中身を変えることができる
- しかし、そうすることによって、今度はdat6の変更によりバイナリファイルが変更されるので、dat1が影響を受ける
- しかし、dat1は相変わらず、親なので、書き換えが可能で、その影響は再度、dat6に戻ってくる
> dat1 uninames$unique.names = TRUE uninames$unique.rownames = TRUE uninames$unique.colnames = TRUE backingfilename = ./tmp727998 cachesizeMb = 64 number of columns (variables) = 3 number of rows (observations) = 4 usedRowIndex: 1 2 3 4 usedColIndex: 1 2 3 Upper-left 3 columns and 4 rows: col1 col2 col3 row1 111 5 9 row2 2 6 10 row3 3 NaN 11 row4 4 8 12 > dat6 uninames$unique.names = TRUE uninames$unique.rownames = TRUE uninames$unique.colnames = TRUE backingfilename = ./tmp727998 cachesizeMb = 64 number of columns (variables) = 2 number of rows (observations) = 2 usedRowIndex: 1 3 usedColIndex: 1 2 Upper-left 2 columns and 2 rows: col1 col2 row1 111 5 row3 3 NaN > dat6[1,1]<-666 Trying to write to the readonly file. 以下にエラー !.Call("assignDoubleMatrix", x@data, newi, newj, as.double(value), : 引数の型が不正です > dat6 uninames$unique.names = TRUE uninames$unique.rownames = TRUE uninames$unique.colnames = TRUE backingfilename = ./tmp727998 cachesizeMb = 64 number of columns (variables) = 2 number of rows (observations) = 2 usedRowIndex: 1 3 usedColIndex: 1 2 Upper-left 2 columns and 2 rows: col1 col2 row1 111 5 row3 3 NaN > setReadOnly(dat6)<-FALSE > dat6[1,1]<-666 > dat6 uninames$unique.names = TRUE uninames$unique.rownames = TRUE uninames$unique.colnames = TRUE backingfilename = ./tmp727998 cachesizeMb = 64 number of columns (variables) = 2 number of rows (observations) = 2 usedRowIndex: 1 3 usedColIndex: 1 2 Upper-left 2 columns and 2 rows: col1 col2 row1 666 5 row3 3 NaN > dat1 uninames$unique.names = TRUE uninames$unique.rownames = TRUE uninames$unique.colnames = TRUE backingfilename = ./tmp727998 cachesizeMb = 64 number of columns (variables) = 3 number of rows (observations) = 4 usedRowIndex: 1 2 3 4 usedColIndex: 1 2 3 Upper-left 3 columns and 4 rows: col1 col2 col3 row1 666 5 9 row2 2 6 10 row3 3 NaN 11 row4 4 8 12 > dat1[1,1]<-1111 > dat1 uninames$unique.names = TRUE uninames$unique.rownames = TRUE uninames$unique.colnames = TRUE backingfilename = ./tmp727998 cachesizeMb = 64 number of columns (variables) = 3 number of rows (observations) = 4 usedRowIndex: 1 2 3 4 usedColIndex: 1 2 3 Upper-left 3 columns and 4 rows: col1 col2 col3 row1 1111 5 9 row2 2 6 10 row3 3 NaN 11 row4 4 8 12 > dat6 uninames$unique.names = TRUE uninames$unique.rownames = TRUE uninames$unique.colnames = TRUE backingfilename = ./tmp727998 cachesizeMb = 64 number of columns (variables) = 2 number of rows (observations) = 2 usedRowIndex: 1 3 usedColIndex: 1 2 Upper-left 2 columns and 2 rows: col1 col2 row1 1111 5 row3 3 NaN >
- この読み取り専用のON/OFFは紐づいている先が本物のテキストファイルでも実施可能
> dat4 uninames$unique.names = TRUE uninames$unique.rownames = TRUE uninames$unique.colnames = TRUE backingfilename = matr1 cachesizeMb = 64 number of columns (variables) = 3 number of rows (observations) = 4 usedRowIndex: 1 2 3 4 usedColIndex: 1 2 3 Upper-left 3 columns and 4 rows: col1 col2 col3 row1 1 5 9 row2 2 6 10 row3 3 NaN 11 row4 4 8 12 > dat4[1,1]<-444 Trying to write to the readonly file. 以下にエラー !.Call("assignDoubleMatrix", x@data, newi, newj, as.double(value), : 引数の型が不正です > setReadOnly(dat4)<-FALSE > dat4[1,1]<-444 > dat4 uninames$unique.names = TRUE uninames$unique.rownames = TRUE uninames$unique.colnames = TRUE backingfilename = matr1 cachesizeMb = 64 number of columns (variables) = 3 number of rows (observations) = 4 usedRowIndex: 1 2 3 4 usedColIndex: 1 2 3 Upper-left 3 columns and 4 rows: col1 col2 col3 row1 444 5 9 row2 2 6 10 row3 3 NaN 11 row4 4 8 12 > dat5 uninames$unique.names = TRUE uninames$unique.rownames = TRUE uninames$unique.colnames = TRUE backingfilename = matr1 cachesizeMb = 64 number of columns (variables) = 3 number of rows (observations) = 4 usedRowIndex: 1 2 3 4 usedColIndex: 1 2 3 Upper-left 3 columns and 4 rows: col1 col2 col3 row1 444 5 9 row2 2 6 10 row3 3 NaN 11 row4 4 8 12
- matrixオブジェクトと同様に使える部分もある
dim(dat1) length(dat1) dimnames(dat1) colnames(dat1) rownames(dat1) dimnames(dat1) <- list(paste("ID", 1:4, sep = ""), paste("SNP", 1:3, sep = "")) dimnames(dat1)
- datableオブジェクト特有の処理
backingfilename(dat1) cachesizeMb(dat1) cachesizeMb(dat1) <- 1 set_dimnames(dat1) <- list(dimnames(dat1)[[1]], c("duplicate", "col2", "duplicate")) get_dimnames(dat1)
- 変更不可能にするにはファイルシステムとの連携を切ればよい
> dat1 uninames$unique.names = TRUE uninames$unique.rownames = TRUE uninames$unique.colnames = TRUE backingfilename = ./tmp727998 cachesizeMb = 64 number of columns (variables) = 3 number of rows (observations) = 4 usedRowIndex: 1 2 3 4 usedColIndex: 1 2 3 Upper-left 3 columns and 4 rows: col1 col2 col3 row1 1111 5 9 row2 2 6 10 row3 3 NaN 11 row4 4 8 12 > dat6 uninames$unique.names = TRUE uninames$unique.rownames = TRUE uninames$unique.colnames = TRUE backingfilename = ./tmp727998 cachesizeMb = 64 number of columns (variables) = 2 number of rows (observations) = 2 usedRowIndex: 1 3 usedColIndex: 1 2 Upper-left 2 columns and 2 rows: col1 col2 row1 1111 5 row3 3 NaN > disconnect(dat1) > dat1 uninames$unique.names = TRUE uninames$unique.rownames = TRUE uninames$unique.colnames = TRUE backingfilename = ./tmp727998 cachesizeMb = 64 number of columns (variables) = 3 number of rows (observations) = 4 usedRowIndex: 1 2 3 4 usedColIndex: 1 2 3 Upper-left 3 columns and 4 rows: col1 col2 col3 row1 1111 5 9 row2 2 6 10 row3 3 NaN 11 row4 4 8 12 > dat6 uninames$unique.names = TRUE uninames$unique.rownames = TRUE uninames$unique.colnames = TRUE backingfilename = ./tmp727998 cachesizeMb = 64 number of columns (variables) = 2 number of rows (observations) = 2 usedRowIndex: 1 3 usedColIndex: 1 2 Upper-left 2 columns and 2 rows: col1 col2 row1 1111 5 row3 3 NaN > dat1[1,1]<-1000 Trying to write to the readonly file. 以下にエラー !.Call("assignDoubleMatrix", x@data, newi, newj, as.double(value), : 引数の型が不正です > dat1 uninames$unique.names = TRUE uninames$unique.rownames = TRUE uninames$unique.colnames = TRUE backingfilename = ./tmp727998 cachesizeMb = 64 number of columns (variables) = 3 number of rows (observations) = 4 usedRowIndex: 1 2 3 4 usedColIndex: 1 2 3 Upper-left 3 columns and 4 rows: col1 col2 col3 row1 1111 5 9 row2 2 6 10 row3 3 NaN 11 row4 4 8 12 > dat6 uninames$unique.names = TRUE uninames$unique.rownames = TRUE uninames$unique.colnames = TRUE backingfilename = ./tmp727998 cachesizeMb = 64 number of columns (variables) = 2 number of rows (observations) = 2 usedRowIndex: 1 3 usedColIndex: 1 2 Upper-left 2 columns and 2 rows: col1 col2 row1 1111 5 row3 3 NaN > dat1[1,1]<-1000 Trying to write to the readonly file. 以下にエラー !.Call("assignDoubleMatrix", x@data, newi, newj, as.double(value), : 引数の型が不正です > dat6[1,1]<-6000 > > dat6 uninames$unique.names = TRUE uninames$unique.rownames = TRUE uninames$unique.colnames = TRUE backingfilename = ./tmp727998 cachesizeMb = 64 number of columns (variables) = 2 number of rows (observations) = 2 usedRowIndex: 1 3 usedColIndex: 1 2 Upper-left 2 columns and 2 rows: col1 col2 row1 6000 5 row3 3 NaN
# datableオブジェクトからmatrixオブジェクトを作る newm <- as(dat2, "matrix") class(dat2) class(newm) class(newm[1, 1])
> newm <- as(dat2, "matrix") > class(dat2) [1] "databel" attr(,"package") [1] "DatABEL" > class(newm) [1] "matrix" > class(newm[1, 1]) [1] "numeric"
#datable オブジェクトからテキストファイルへの書き出し databel2text(dat2, file = "dat2.txt") # dat2.txtファイルができていて、R内から読める read.table("dat2.txt")
> read.table("dat2.txt") col1 col2 col3 row1 222 55 9 row2 2 6 10 row3 3 NA 11 row4 4 8 12
- そして、このdatableオブジェクトを使うとapply()関数のようなことができる(それはそれほどびっくりではない)
unlink("tmp*") a <- matrix(rnorm(50),10,5) rownames(a) <- paste("id",1:10,sep="") colnames(a) <- paste("snp",1:5,sep="") b <- as(a,"databel") apply(a,FUN="sum",MAR=2) apply2dfo(SNP,dfodata=b,anFUN="sum")
- けれど、apply()関数的に、線形回帰とかも(しかも次数が高くできて、多項にできて…)
apply(a,FUN="sum",MAR=2) apply2dfo(SNP,dfodata=b,anFUN="sum") y<-runif(length(a[,1])) apply2dfo(y~SNP,dfodata=b,anFUN="lm",MAR=2) apply2dfo(y~SNP+SNP^2,dfodata=b,anFUN="lm",MAR=2)