2

私は次のdata.tablesようなものを持っています:

x <- data.table(id=rep(1:3, 2), a=1:6)
y <- data.table(id=1:3, b=2:4)

次のようにマージできます。

setkey(x, id)
setkey(y, id)
x[y]
   id a b
1:  1 1 2
2:  1 4 2
3:  2 2 3
4:  2 5 3
5:  3 3 4
6:  3 6 4

今、オフにx基づいて新しい列を作成したいと思います。これはとの合計です。私はこれを行うことができます:abab

x[y, val:=a + b]

しかし、何らかの理由で '+' 演算子がベクトル化されていないとします。計算に必要なx場所に行単位の計算を格納するにはどうすればよいですか? x[y]また、使用できないと仮定しますmapply(実際の問​​題でmapplyは、機能に適していないため)。

私はsapply行ごとに追加するためにそのように使用しようとしています:

x[y, sapply(1:nrow(x), function (i) a[i] + b[i])]

ただし、これは間違った結果を返します。

    id V1
 1:  1  3
 2:  1 NA
 3:  1 NA
 4:  1 NA
 5:  1 NA
 6:  1 NA
 7:  2  5
 8:  2 NA
 9:  2 NA
10:  2 NA
11:  2 NA
12:  2 NA
13:  3  7
14:  3 NA
15:  3 NA
16:  3 NA
17:  3 NA
18:  3 NA

私がこれを行うと、動作します:

x[y][, sapply(1:nrow(x), function (i) a[i] + b[i])]
# [1] 3 6 5 8 7 10

しかし、これを の列に割り当てようとすると、x保存されません (新しい列を に保存しようとしているように見えるので理にかなっていますx[y])。

x[y][, val:=sapply(1:nrow(x), function (i) a[i] + b[i])]

上記を実行して出力を に保存する方法はありますx[, val]か? これは私がそれを行うことになっている方法ですか、それともより多くのdata.table方法がありますか?

x[, val:=x[y][, sapply(1:nrow(x), function (i) a[i] + b[i])]]
4

1 に答える 1

5

あなたはby-without-byそれを知らずにやっています(ヘルプの説明については以下を参照してください)

高度: 既知のグループのサブセットの集計は、それらのグループを i で渡す場合に特に効率的です。i が data.table の場合、DT[i,j] は i の行ごとに j を評価します。これを by なし、または i によるグループ化と呼びます。したがって、自己結合 DT[data.table(unique(colA)),j] は DT[,j,by=colA] と同じです。

これは、 (一度に1 行ずつ循環する)jの行ごとに評価されることを意味します。これを実行すると、必要なときに毎回長さのベクトルが作成されます。iysapply(1:nrow(x),...)jnrow(x)

したがって、2番目のオプションは間違いなく有効なアプローチです(これは、これを行うための推奨されるアプローチの1つです)

それ以外の場合は.N( i でグループ化する場合、.N は i の各行について、一致する x の行数です) を使用できませんnrow(x)が、オブジェクトの長さと関数をベクトル化する方法について考える必要があります。 .

これを例に取ります

x[y, {browser(); a+b}]
Called from: `[.data.table`(x, y, {
    browser()
    a + b
})
Browse[1]> a
[1] 1 4
Browse[1]> b
[1] 2
Browse[1]> .N
[1] 2

aキーの値が x の 2 行と一致するため、長さは 2 です。の長さは 1 インチしかないため、b長さしかありません。 1y

最善のアプローチは、関数を正しくベクトル化することだと思います (これについては、例がなくてもアドバイスするのは難しいです)。

別のアプローチは、たとえばbの長さに複製することですa

 x[y, val := {
 bl <- rep_len(b, .N)
 sapply(seq_len(.N), function(i) a[i] + bl[i])}]
x
   id a val
1:  1 1   3
2:  1 4   6
3:  2 2   5
4:  2 5   8
5:  3 3   7
6:  3 6  10

yまたは、の値ごとに一意の行があることがわかっている場合はid、そこから列にインデックスを付けようとする必要はありません。

x[y, val2 := sapply(seq_len(.N), function(i) a[i] + b)]
# an alternative would be to use sapply on a (avoid creating another vector)
x[y, val3 := sapply(a, function(ai) ai + b)]
x
#    id a val val2 val3
# 1:  1 1   3    3    3
# 2:  1 4   6    6    6
# 3:  2 2   5    5    5
# 4:  2 5   8    8    8
# 5:  3 3   7    7    7
# 6:  3 6  10   10   10
于 2013-04-30T04:25:39.040 に答える