2017-08-28 8 views
5

私はturn == 3N番目の発生時に、-1に「DIS」を変更したいdata.table別の変数のn番目の値で変数を変更するにはどうすればよいですか?

library(data.table) 
car <- data.table(no = 1:100, turn = sample(1:5,100,replace = TRUE), 
       dis = sample(1:10,100,replace = TRUE)) 

があり、「ターン」という第三の時間が3であると言います。

私はturn == 3の三行を選択することができます

car[turn == 3, .SD[3]][, dis := -1] 

関連するQ & A:Conditionally replacing column values with data.tableしかし、私は "DIS" この行でを更新するために管理していない

car[turn == 3, .SD[3]] 

を。

+0

この行の検索方法は問題ありません。これはHenrikの似たような方法です: 'car [cumsum(turn == 3)== 3&(turn == 3)、dis:= -1]' – mt1022

+0

正しい。次回を依頼する方法を学ぶことができquestion.Iを編集するには、 ' –

答えて

6

いくつかの選択肢。グループ内に行カウンタを作成するには、rowidまたはcumsumを使用します。 iにあなたの状態にカウンターを追加してください。

私はちょうどそれが簡単に変更を追跡するために作るために、わずかに小さいおもちゃのデータセットを使用します。

d <- data.table(x = 1:3, y = 1:12) 

d[rowid(x) == 3 & x == 3, y := -1] 

# @mt1022 
d[cumsum(x == 3) == 3 & (x == 3), y := -1] 

# @docendo discimus 
d[(ix <- x == 3) & cumsum(ix) == 3, y := -1] 

OPが問題としてスピードは言及しなかったが、私はまだ時間に興味がありましたより大きなベクトル上の異なるアプローチ。当然のことながら、ユニークな値の数は増加の中で検索したときにフランクの方法@特にそう、最速です:

frank << docendo < henrik < mt022

microbenchmark(henrik = d[rowid(x) == 3 & x == 3, y := -1], 
       mt1022 = d[cumsum(x == 3) == 3 & (x == 3), y := -1], 
       docendo = d[(ix <- x == 3) & cumsum(ix) == 3, y := -1], 
       frank = d[d[x == 3, which = TRUE][3], y := -1], unit = "relative") 

d <- data.table(x = sample(1:3, 1e6, replace = TRUE), y = 1:1e6) 
# Unit: relative 
# expr  min  lq  mean median  uq  max neval cld 
# henrik 4.417303 4.369407 4.133514 4.319839 4.329658 1.260394 100 b 
# mt1022 5.461961 5.285562 5.174559 5.186404 5.239738 1.608712 100 c 
# docendo 3.572646 3.624369 3.788678 3.589705 3.576637 1.733272 100 b 
# frank 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 100 a 

d <- data.table(x = sample(1:30, 1e6, replace = TRUE), y = 1:1e6) 
# Unit: relative 
# expr  min  lq  mean median  uq  max neval cld 
# henrik 22.64881 19.54375 18.81963 18.91335 19.78559 5.507692 100 bc 
# mt1022 24.58258 21.17535 19.84417 20.96256 22.76020 3.625263 100 c 
# docendo 19.40044 16.75912 16.23321 16.47953 18.06264 4.234100 100 b 
# frank 1.00000 1.00000 1.00000 1.00000 1.00000 1.000000 100 a 

d <- data.table(x = sample(1:300, 1e6, replace = TRUE), y = 1:1e6) 
# Unit: relative 
# expr  min  lq  mean median  uq  max neval cld 
# henrik 31.81237 32.51122 28.79490 30.35766 28.63560 8.236282 100 b 
# mt1022 34.71984 35.45341 33.20405 33.57394 31.50914 21.556367 100 c 
# docendo 27.99046 28.15855 26.56954 26.60644 25.20044 7.847163 100 b 
# frank 1.00000 1.00000 1.00000 1.00000 1.00000 1.000000 100 a 

# Unit: milliseconds 
# expr  min  lq  mean median  uq  max neval cld 
# henrik 60.655582 76.455531 83.061266 77.632036 78.57818 203.224042 100 c 
# mt1022 66.701182 84.133034 87.967300 84.937201 85.72464 201.167914 100 c 
# docendo 52.938545 67.214360 71.558130 68.003891 68.51897 184.178346 100 b 
# frank 1.977821 2.494039 2.629852 2.663577 2.76089 3.613905 100 a 
+1

ありがとう: - '車[= -1&CUMSUM(X)== 3、DIS(ターン== 3×<):]ここに似たです。 –

+0

@docendo discimus私はあなたの素晴らしい提案を私の答えに含めました。必要に応じて、別の回答を削除して投稿してください。 – Henrik

+1

@フランク... '私は考えていなかった...ずっと良い!私はそれをupvoteことができるように答えとして投稿してください! – Henrik

3

ここでは別の方法です:

car[car[turn == 3, which = TRUE][3], dis := -1 ] 

コメント。このような操作では、verboseをオンにして、変更が行われたかどうかを確認することができます。たとえば、111th 3を検索した場合....

car[car[turn == 3, which = TRUE][111], dis := -1, verbose = TRUE ] 
# Detected that j uses these columns: dis 
# Assigning to 0 row subset of 100 rows 

これは、0行が編集されたことを示しています。


which = TRUEの使用にもUsing .I to return row numbers with data.table package参照してください。

関連する問題