2

data.framesを使用して次のコードがありますが、最も効率的で最もベクトル化されたコードを使用して、data.tablesを使用してこれを作成する方法を知りたいですか?

data.frameコード:

set.seed(1)
to <- cbind(data.frame(time=seq(1:5),bananas=sample(100,5),apples=sample(100,5)),setNames(data.frame(matrix(sample(100,90,replace=T),nrow=5)),paste0(1:18)))
from <- cbind(data.frame(time=seq(1:5),blah=sample(100,5),foo=sample(100,5)),setNames(data.frame(matrix(sample(100,90,replace=T),nrow=5)),paste0(1:18)))
from
to

rownames(to) <- to$time
to[as.character(from$time),paste0(1:18)] <- from[,paste0(1:18)]
to

これを実行する:

>     set.seed(1)
>     to <- cbind(data.frame(time=seq(1:5),bananas=sample(100,5),apples=sample(100,5)),setNames(data.frame(matrix(sample(100,90,replace=T),nrow=5)),paste0(1:18)))
>     from <- cbind(data.frame(time=seq(1:5),blah=sample(100,5),foo=sample(100,5)),setNames(data.frame(matrix(sample(100,90,replace=T),nrow=5)),paste0(1:18)))
>     from
  time blah foo  1  2   3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18
1    1   66  22 98  2 100 46 58 60 69 46 62 19 29 42 64 90 30 19 72 60
2    2   35  13 74 72  50 52  8 57 61 18 56 53 90  7 85 65 20 76 39 12
3    3   27  47 36 11  49 21  4 53 24 75 33  8 45 34 86 75 89 73 11 85
4    4   97  90 44 45  18 23 65 99 26 11 46 28 78 73 40 61 51 95 93 32
5    5   61  58 15 65  76 60 93 51 73 87 51 22 89 34 39 91 88 55 29 79
>     to
  time bananas apples  1   2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18
1    1      27     90 21  50 94 39 49 67 83 79 48 10 92 26 34 90 44 21 24 80
2    2      37     94 18  72 22  2 60 80 65  3 87 32 30 48 84 87 72 72  6 46
3    3      57     65 69 100 66 39 50 11 79 48 44 52 46 77 35 39 40 13 65 42
4    4      89     62 39  39 13 87 19 73 56 74 25 67 34  9 34 78 33 25 88 82
5    5      20      6 77  78 27 35 83 42 53 70  8 41 66 88 48 97 76 15 78 61
> 
>     rownames(to) <- to$time
>     to[as.character(from$time),paste0(1:18)] <- from[,paste0(1:18)]
>     to
  time bananas apples  1  2   3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18
1    1      27     90 98  2 100 46 58 60 69 46 62 19 29 42 64 90 30 19 72 60
2    2      37     94 74 72  50 52  8 57 61 18 56 53 90  7 85 65 20 76 39 12
3    3      57     65 36 11  49 21  4 53 24 75 33  8 45 34 86 75 89 73 11 85
4    4      89     62 44 45  18 23 65 99 26 11 46 28 78 73 40 61 51 95 93 32
5    5      20      6 15 65  76 60 93 51 73 87 51 22 89 34 39 91 88 55 29 79

基本的に、の列からの列paste0(1:18)を更新し、sを一致させます。topaste0(1:18)fromtime

data.tableコンソールで印刷するときにヘッドが不要ななどのメリットがあるようですので、使ってみようと思います。

ただし、式を手で書く必要はありません:=。つまり、次のことは避けてください。

to[from,`1`:=i.`1`,`2`:=i.`2`, ..]

また、可能であれば、ある種のforループではなく、ベクトル化された構文を使用することをお勧めします。つまり、次のようなものは避けてください。

for( i in 1:18 ) {
    to[from, sprintf("%d",i) := i.sprintf("%d",i)]
}

よくある質問のビネットとdatatable-introのビネットを読みましたが、おそらくすべてを100%理解しているわけではないことは認めます。

data.tableの列をループしてそれらの列を変換しましたが、100%理解できているとは言えず、forループを使用する必要があると思われますか?

8374816の下部には、データフレーム構文を使用するだけでよい可能性があるというヒントがあるようwith=FALSEです。しかし、data.frameプロシージャが行名をハッキングしているため、それがどの程度うまく機能するかはわかりません。data.tableの効率をどの程度活用できるのでしょうか。

4

1 に答える 1

2

良い質問。あなたが示した基本構成:

to[as.character(from$time),paste0(1:18)] <- from[,paste0(1:18)]

行名を複製できないことを前提として機能します。複製できない場合は、最初の名前のみが一致します。ここで、のLHSは<-、のRHSと同じ行数になります<-

data.table日常的に、の複数の行toが一致する可能性があるため、は異なります。のデフォルトはmultです"all"data.tableまた、ワイドよりもロングフォーマットを好みます。したがって、この質問は、data.table実際には設計されていないもののペースを調整するようなものです。これらの18列にいずれかがある場合NA(つまりスパース)、長い形式の方が適切な場合があります。18列すべてが同じタイプの場合は、aのmatrix方が適切な場合があります。

とはいえ、完全を期すための3つdata.tableのオプションがあります。

1. :=forループを使用しますが、使用しません(LHS:= RHSの複数のLHSと複数のRHS)

from = as.data.table(from)
to = as.data.table(to)
from
   time blah foo  1  2   3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18
1:    1   66  22 98  2 100 46 58 60 69 46 62 19 29 42 64 90 30 19 72 60
2:    2   35  13 74 72  50 52  8 57 61 18 56 53 90  7 85 65 20 76 39 12
3:    3   27  47 36 11  49 21  4 53 24 75 33  8 45 34 86 75 89 73 11 85
4:    4   97  90 44 45  18 23 65 99 26 11 46 28 78 73 40 61 51 95 93 32
5:    5   61  58 15 65  76 60 93 51 73 87 51 22 89 34 39 91 88 55 29 79
to
   time bananas apples  1   2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18
1:    1      27     90 21  50 94 39 49 67 83 79 48 10 92 26 34 90 44 21 24 80
2:    2      37     94 18  72 22  2 60 80 65  3 87 32 30 48 84 87 72 72  6 46
3:    3      57     65 69 100 66 39 50 11 79 48 44 52 46 77 35 39 40 13 65 42
4:    4      89     62 39  39 13 87 19 73 56 74 25 67 34  9 34 78 33 25 88 82
5:    5      20      6 77  78 27 35 83 42 53 70  8 41 66 88 48 97 76 15 78 61
setkey(to,time)
setkey(from,time)
to[from,paste0(1:18):=from[.GRP,paste0(1:18),with=FALSE]]
   time bananas apples  1  2   3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18
1:    1      27     90 98  2 100 46 58 60 69 46 62 19 29 42 64 90 30 19 72 60
2:    2      37     94 74 72  50 52  8 57 61 18 56 53 90  7 85 65 20 76 39 12
3:    3      57     65 36 11  49 21  4 53 24 75 33  8 45 34 86 75 89 73 11 85
4:    4      89     62 44 45  18 23 65 99 26 11 46 28 78 73 40 61 51 95 93 32
5:    5      20      6 15 65  76 60 93 51 73 87 51 22 89 34 39 91 88 55 29 79

また

to[from,paste0(1:18):=from[,paste0(1:18),with=FALSE],mult="first"]
   time bananas apples  1  2   3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18
1:    1      27     90 98  2 100 46 58 60 69 46 62 19 29 42 64 90 30 19 72 60
2:    2      37     94 74 72  50 52  8 57 61 18 56 53 90  7 85 65 20 76 39 12
3:    3      57     65 36 11  49 21  4 53 24 75 33  8 45 34 86 75 89 73 11 85
4:    4      89     62 44 45  18 23 65 99 26 11 46 28 78 73 40 61 51 95 93 32
5:    5      20      6 15 65  76 60 93 51 73 87 51 22 89 34 39 91 88 55 29 79

オプション1が機能するために必要な最新のv1.8.3を使用していることに注意してください(.GRP追加されたばかりで、アウターwith=FALSEは不要になりました)。

2. 18列ではなく、1つのリスト列を使用して長さ18のベクトルを格納します

to = data.table( time=seq(1:5),
                 bananas=sample(100,5),
                 apples=sample(100,5),  
                 v18=replicate(5,sample(100,18),simplify=FALSE))
from =  data.table( time=seq(1:5),
                    blah=sample(100,5),
                    foo=sample(100,5),
                    v18=replicate(5,sample(100,18),simplify=FALSE))
setkey(to,time)
setkey(from,time)

from
   time blah foo                 v18
1:    1   56  97   88,47,1,71,69,18,
2:    2   69  40   96,99,60,3,33,27,
3:    3   65  84 100,38,56,72,84,55,
4:    4   98  74 91,69,24,63,27,100,
5:    5   46  52    65,4,59,41,8,51,

to
   time bananas apples                 v18
1:    1      66     73 100,36,74,77,68,46,
2:    2      19     37   84,88,92,8,37,52,
3:    3      94     77   37,94,13,7,93,43,
4:    4      88      2  27,93,71,16,46,66,
5:    5      91     91   85,94,58,49,19,1,

to[from,v18:=i.v18]
to
   time bananas apples                 v18
1:    1      66     73   88,47,1,71,69,18,
2:    2      19     37   96,99,60,3,33,27,
3:    3      94     77 100,38,56,72,84,55,
4:    4      88      2 91,69,24,63,27,100,
5:    5      91     91    65,4,59,41,8,51,

列の印刷を一覧表示することに慣れていない場合、末尾のコンマは、そのベクトルにさらに多くの項目があることを示します。最初の6つだけが印刷されます。

3.data.frameで構文を使用しますdata.table

to = as.data.table(to)
from = as.data.table(from)
setkey(to,time)
setkey(from,time)

from
   time blah foo  1  2   3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18
1:    1   66  22 98  2 100 46 58 60 69 46 62 19 29 42 64 90 30 19 72 60
2:    2   35  13 74 72  50 52  8 57 61 18 56 53 90  7 85 65 20 76 39 12
3:    3   27  47 36 11  49 21  4 53 24 75 33  8 45 34 86 75 89 73 11 85
4:    4   97  90 44 45  18 23 65 99 26 11 46 28 78 73 40 61 51 95 93 32
5:    5   61  58 15 65  76 60 93 51 73 87 51 22 89 34 39 91 88 55 29 79

to
   time bananas apples  1   2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18
1:    1      27     90 21  50 94 39 49 67 83 79 48 10 92 26 34 90 44 21 24 80
2:    2      37     94 18  72 22  2 60 80 65  3 87 32 30 48 84 87 72 72  6 46
3:    3      57     65 69 100 66 39 50 11 79 48 44 52 46 77 35 39 40 13 65 42
4:    4      89     62 39  39 13 87 19 73 56 74 25 67 34  9 34 78 33 25 88 82
5:    5      20      6 77  78 27 35 83 42 53 70  8 41 66 88 48 97 76 15 78 61

to[from, paste0(1:18)] <- from[,paste0(1:18),with=FALSE]
to
   time bananas apples  1  2   3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18
1:    1      27     90 98  2 100 46 58 60 69 46 62 19 29 42 64 90 30 19 72 60
2:    2      37     94 74 72  50 52  8 57 61 18 56 53 90  7 85 65 20 76 39 12
3:    3      57     65 36 11  49 21  4 53 24 75 33  8 45 34 86 75 89 73 11 85
4:    4      89     62 44 45  18 23 65 99 26 11 46 28 78 73 40 61 51 95 93 32
5:    5      20      6 15 65  76 60 93 51 73 87 51 22 89 34 39 91 88 55 29 79

したがって、のLHSはキー付き結合構文<-を使用できます。data.tableすなわちto[from]。このメソッド(現在はR)がデータセット全体 toをコピーするだけです。これ:=は、参照による更新を提供することによって回避するために導入されたものです。また、の各行fromがの複数の行と一致する場合to、のRHSは<-(ユーザーが)整列するように拡張する必要があります。そうでない場合、RHSはLHSを埋めるためにリサイクルされます。data.tableそれが、私たち:=が中jにいるのが好きな理由の1つ[...]です。

于 2012-10-23T20:38:14.520 に答える