0

data.table以下に示すように、2つの s があります。

N = 10
A.DT <- data.table(a1 = c(rnorm(N,0,1)), a2 = NA))
B.DT <- data.table(b1 = c(rnorm(N,0,1)), b2 = 1:N)
setkey(A.DT,a1)    
setkey(B.DT,b1)

以下に示すように for ループを変更して、以前data.frameの実装を実装に変更しようとしました。data.table

for (i in 1:nrow(B.DT)) {
  for (j in nrow(A.DT):1) {
    if (B.DT[i,b2] <= N/2 
        && B.DT[i,b1] < A.DT[j,a1]) {
      A.DT[j,]$a2 <- B.DT[i,]$b1
      break
    }
  }
} 

次のエラー メッセージが表示されます。

Error in `[<-.data.table`(`*tmp*`, j, a2, value = -0.391987468746123) : 
  object "a2" not found

アクセス方法がいまいちだと思いますdata.table。私はそれに慣れていません。2 つのデータテーブルを上下に循環させるよりも簡単な方法があると思います。

上記のループを単純化/ベクトル化できるかどうかを知りたいです。

コピー/貼り付け用の data.table データを編集します。

# A.DT
    a1  a2
1   -1.4917779  NA
2   -1.0731161  NA
3   -0.7533091  NA
4   -0.3673273  NA
5   -0.159569   NA
6   -0.1551948  NA
7   -0.0430574  NA
8   0.1783496   NA
9   0.4276034   NA
10  1.0697412   NA

# B.DT
    b1  b2
1   0.64229018  1
2   1.00527902  2
3   0.24746294  3
4   -0.50288835 4
5   0.34447791  5
6   -0.22205129 6
7   0.60099079  7
8   -0.70242284 8
9   0.6298599   9
10  0.08917988  10

私が期待する出力:

# OUTPUT
    a1  a2
1   -1.4917779  NA
2   -1.0731161  NA
3   -0.7533091  NA
4   -0.3673273  NA
5   -0.159569   NA
6   -0.1551948  NA
7   -0.0430574  NA
8   0.1783496   -0.50288835
9   0.4276034   0.24746294
10  1.0697412   0.64229018

アルゴリズムは 1 つのテーブルを下に移動し、行ごとにもう一方のテーブルを上に移動し、いくつかの条件を確認し、それに応じて値を変更します。より具体的には、B.DT を下に移動し、B.DT の各行に対して A.DT を上に移動し、b1 が a1 より小さくなるように b1 の最初の値を a2 に割り当てます。割り当ての前に、追加の条件がチェックされます (この例では、b2 が 5 以下である)。

0.64229018 は B.DT の最初の値であり、A.DT の最後のユニットに割り当てられます。1.00527902 は B.DT の 2 番目の値ですが、A.DT の他のすべての値よりも大きいため、割り当てられていません。0.24746294 は B.DT の 3 番目の値であり、A.DT の最後から 2 番目の単位に割り当てられます。-0.50288835 は B.DT の 4 番目の値であり、A.DT のユニット #8 に割り当てられています。0.34447791 は B.DT の 5 番目の値であり、大きすぎるため割り当てられていません。

もちろん、これは単純化された問題です (したがって、あまり意味がないかもしれません)。お時間をいただきありがとうございます。

4

2 に答える 2

1

コードは次のように変更されます。

A.DT[j,]$a2 <- B.DT[i,]$b1

A.DT$a2[j,] <- B.DT[i,]$b1

のより効率的な使用についてはdata.table、私よりも専門家に任せます...

于 2013-03-18T12:00:59.750 に答える
1

data.table を作成したら、通常の assign operator を使用する必要はほとんど<-なく、代わりに を使用します。:=これは、場所の括弧内に入りますj。(回避する理由は、オブジェクトのコピーを作成するのに対し、作成<-しないため、効率が向上するためです)<-:=

したがって、コードの最初の変更は次のようになります。

 # FROM: A.DT[j,]$a2 <- B.DT[i,]$b1
 # TO: 
 A.DT[j, a2 := B.DT[i, b1] ]

さて、data.tableの (多くの) 最高の機能の1 つは引数です。これは、多くのループと呼び出しをなくすbyのに役立ちます。この特定のケースでは、次のようにデュアル ループをクリーンアップできます。for*ply

set.seed(201)
A.DT <- data.table(a1 = rnorm(N,0,1), key="a1")  # no need to create a2 if it will be NA. If you do, make sure it is as.numeric(NA)
B.DT <- data.table(b1 = rnorm(N,0,1), b2 = 1:N, key="b2")

# Assign to a2 in A.DT
A.DT[            
      , a2 := B.DT[ b2 <= N/2 & b1 < a1] [1, b1]
      , by=a1
     ]


> A.DT
             a1         a2
 1: -2.30403431         NA
 2: -1.69658097         NA
 3: -1.28548252         NA
 4: -0.34454603 -0.6478531
 5: -0.07503189 -0.6478531
 6:  0.05593404 -0.6478531
 7:  0.18900414 -0.6478531
 8:  0.26693735  0.2238094
 9:  0.28606069  0.2238094
10:  0.32576373  0.2238094

s の2 つの補足事項key

  • data.table の作成と同時にキーを設定できるため、2 行のコードを節約できます。
  • data.table はそのキーでソートされます。行の位置を使用して割り当てを決定しているという事実から判断すると、キーを設定したくないと思います。上記のコードでは、B.DTのキーを `b2.
于 2013-03-21T03:05:20.473 に答える