データファイルを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)