R_winBUGS_structure のバックアップ差分(No.6) - アールメカブ

アールメカブ


R_winBUGS_structure のバックアップ差分(No.6)


  • 追加された行はこの色です。
  • 削除された行はこの色です。
[[Rの備忘録]]

structure 関数が R では,縦方向に行列を埋めていくのに対して,winBUGS では横方向にデータを埋めていくのであった.例えば以下は

 structure(
    .Data = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
    .Dim=c(5,2)

winBUGS では

 [1] 1 2 3 4 5
 [2] 6 7 8 9 10

となるが(winBUGSのメニュー[Info]-[Node Info]-[y]-[values]で確認してみた),R では

 [1] 1 3 5 7 9 
 [2] 2 4 6 8 10

となる.

また

 y=structure(
  .Data = c(75, 57, 10, 66, 74, 40, 52, 60, 54,  9, 64, 58,
            63, 31, 63, 58, 67, 44, 20, 53, 65, 10, 42, 20), 
  .Dim = c(2, 3, 4)))

はwinBUGSでは,最後に指定された3次元の 4 個ずつにデータを分け,それを1次元目の最初の1行目について,2時限目の各列を埋めていくという発想なので,
はwinBUGSでは,最後に指定された3次元眼で指定された 4 個ずつにデータを分け,それを1次元目の最初の各行ごとに右方向に,2次元の各列を埋めていくという発想なので,

 model compiled
 y[1,1,1]      75.0
 y[1,1,2]      57.0
 y[1,1,3]      10.0
 y[1,1,4]      66.0
 y[1,2,1]      74.0
 y[1,2,2]      40.0
 y[1,2,3]      52.0
 y[1,2,4]      60.0
 y[1,3,1]      54.0
 y[1,3,2]      9.0
 y[1,3,3]      64.0
 y[1,3,4]      58.0
 y[2,1,1]      63.0
 y[2,1,2]      31.0
 y[2,1,3]      63.0
 y[2,1,4]      58.0
 y[2,2,1]      67.0
 y[2,2,2]      44.0
 y[2,2,3]      20.0
 y[2,2,4]      53.0
 y[2,3,1]      65.0
 y[2,3,2]      10.0
 y[2,3,3]      42.0
 y[2,3,4]      20.0

と展開される。これはRの配列で書くと

 ,,1
  75  74  54
  63  67  65 
 ,,2
  57  40  9
  31  44  10
 ,,3
  10  52  64
  63  20  42
 ,,4
  66  60  58
  58  53  20

ということになるが,しかしRで同じstructure()関数を実行すると

 y=structure(
  .Data = c(75, 57, 10, 66, 74, 40, 52, 60, 54,  9, 64, 58,
            63, 31, 63, 58, 67, 44, 20, 53, 65, 10, 42, 20), 
  .Dim = c(2, 3, 4)))

結果は

 , , 1
       [,1] [,2] [,3]
 [1,]   75   10   74
 [2,]   57   66   40
  , , 2
       [,1] [,2] [,3]
 [1,]   52   54   64
 [2,]   60    9   58
  , , 3
       [,1] [,2] [,3]
 [1,]   63   63   67
 [2,]   31   58   44
  , , 4
       [,1] [,2] [,3]
 [1,]   20   65   42
 [2,]   53   10   20

となってしまう.winBUGSのstructure()関数と同じ配列を作成するためには以下のようにしなければならない.

 y = structure(
       .Data = c(75, 63, 57, 31, 10, 63, 66, 58, 74, 67, 40, 44, 52, 
                  20, 60, 53, 54, 66, 9, 10, 64, 42, 58, 20), 
        .Dim = c(2, 3, 4))

すなわち

 75, 57, 10, 66, 74, 40, 52, 60, 54,  9, 64, 58, 
 63, 31, 63, 58, 67, 44, 20, 53, 65, 10, 42, 20

を

 75, 63, 57, 31, 10, 63, 66, 58, 74, 67, 40, 44, 
 52, 20, 60, 53, 54, 66, 9, 10, 64, 42, 58, 20

と並び替える.3*4 個ずつずれるのである.だから,手っ取り早くは次のようにして並び替えができる.


 y <- numeric()
 for(i in 1: length(x)){
   y <- c(y,  x[seq(i, length(x), 12) ])
   if(length(y) >= length(x)) break
 }



また先のwinBUGSの配列は R のデータフレーム流に書くと

 > df.array <- data.frame(I = c(rep("1",12), rep("2",12)), 
              J = c( rep("1",4), rep("2", 4), rep("3", 4)), 
              K = c(75, 57, 10, 66, 74, 40, 52, 60, 54, 9, 
                      64, 58, 63, 31, 63, 58, 67, 44, 20, 53, 
                      65, 10, 42, 20))

 > df.array
   I J  K
 1  1 1 75
 2  1 1 57
 3  1 1 10
 4  1 1 66
 5  1 2 74
 6  1 2 40
 7  1 2 52
 8  1 2 60
 9  1 3 54
 10 1 3  9
 11 1 3 64
 12 1 3 58
 13 2 1 63
 14 2 1 31
 15 2 1 63
 16 2 1 58
 17 2 2 67
 18 2 2 44
 19 2 2 20
 20 2 2 53
 21 2 3 65
 22 2 3 10
 23 2 3 42
 24 2 3 20

ということになる.

http://www.mrc-bsu.cam.ac.uk/bugs/winbugs/manual14.pdf 
の17ページに詳しく書いてある.が,このファイルの説明は R ではうまくいかない.

変換は,行列であれば転置すれば良いだけだが,配列だとやっかいだな.作成時にstructure()関数に引数を与えることで,横方向に埋めることは可能なのだろうか?


 M <- matrix(1:10, ncol = 2)
 str(M)
 # int [1:5, 1:2] 1 2 3 4 5 6 7 8 9 10
 str(t(M))
 # int [1:2, 1:5] 1 6 2 7 3 8 4 9 5 10
 dput(M, file = "M.txt")
 # structure(1:10, .Dim = c(5L, 2L))
 dput(t(M), file = "M.txt")
 # structure(c(1L, 6L, 2L, 7L, 3L, 8L, 4L, 9L, 5L, 10L), 
   .Dim = c(2L,  5L))

うーーん,効率的な方法は何だろうか.

ちなみに上の出力の数字の後にLがあるが,これは整数値として保存されていることを意味する.

Rのメーリングリストで [R] Bug in "is" ? という話題があった.その2008年9月25日の回答に以下のようなものがあった.
>
Mathematicians are concerned with properties of numbers, computer scientists are concerned with how numbers are stored (and statisticians when doing statistics are more concerned with data than numbers).  R is an implementation of the S programming language (along with many tools written in that language) so fits in more with the computer scientist view than the mathematical view.  So, is.integer is telling you about how 7 is stored, not the property of the number 7.  If we write 7L then we tell R/S that we want 7 stored as an integer, if we write 7. or 7.0 then we tell R/S to store it as double precision, but with 7 it has to guess which we want, and since the real numbers are closed to more operations than the integers (and double precision is the chosen approximation to real), it seems the more practical default.
Greg Snow
<