2016-03-14 8 views
5

新しい列をdata.tableに追加しようとしています。この場合、行の値は行の値の相対的な関係に依存します。より正確に言えば、行内に値Xがある場合、同じ列(およびグループ)内の他の値がX-30内にどれくらいあるか知りたいと思います。グループごとにdata.tableのウィンドウ内の値の数を数えてください

この与えられ、次のとおりです。

DT<-data.table(
X = c(1, 2, 2, 1, 1, 2, 1, 2, 2, 1, 1, 1), 
Y = c(100, 101, 133, 134, 150, 156, 190, 200, 201, 230, 233, 234), 
Z = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)) 

私は値で、新しい列を取得したいと思います:

N <- c(0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 2) 

私は次のことを試してみたが、私は得ることはありません私が使用できる結果:

DT[,list(Y,num=cumsum(Y[-.I]>DT[.I,Y]-30),Z),by=.(X)] 

どのようにこれを行うには?

答えて

6

これはおそらく、ローリングと結合達成することができているが、ここでは今

DT[, `:=`(indx = .I, Y2 = Y - 30L, N = 0L)] # Add row index and a -30 interval 
setkey(DT, X, Y2, Y) # Sort by X and the intervals (for fovelaps) 
res <- foverlaps(DT, DT)[Y2 > i.Y2, .N, keyby = indx] # Run foverlaps and check what can we catch 
setorder(DT, indx) # go back to the original order 
DT[res$indx, N := res$N][, c("indx", "Y2") := NULL] # update results and remove cols 
DT 
#  X Y Z N 
# 1: 1 100 1 0 
# 2: 2 101 2 0 
# 3: 2 133 3 0 
# 4: 1 134 4 0 
# 5: 1 150 5 1 
# 6: 2 156 6 1 
# 7: 1 190 7 0 
# 8: 2 200 8 0 
# 9: 2 201 9 1 
# 10: 1 230 10 0 
# 11: 1 233 11 1 
# 12: 1 234 12 2 

代わりためfoverlaps代替である、オーバーラップが小さく合併にするfoverlapswhich=TRUEオプションを使用します(?):

# as above 
DT[, `:=`(indx = .I, Y2 = Y - 30L, N = 0L)] 
setkey(DT, X, Y2, Y) 

# using which=TRUE: 
res <- foverlaps(DT, DT, which=TRUE)[xid > yid, .N, by=xid] 
DT[res$xid, N := res$N] 
setorder(DT, indx) 
DT[, c("Y2","indx") := NULL] 
4

は、ここに別の方法です:

DT[order(Y), N := 0:(.N-1) - findInterval(Y - 30, Y), by = X] 

all.equal(DT$N,N) # TRUE 
関連する問題