Lets say I have a data table like this.
customer_id time_stamp value
1: 1 223 4
2: 1 252 1
3: 1 456 3
4: 2 455 5
5: 2 632 2
そのため、customer_id と time_stamp が一緒になって一意のキーを形成します。「値」の前と最後の値を示す新しい列をいくつか追加したいと思います。つまり、このような出力が必要です。
customer_id time_stamp value value_PREV value_NEXT
1: 1 223 4 NA 1
2: 1 252 1 4 3
3: 1 456 3 1 NA
4: 2 455 5 NA 2
5: 2 632 2 5 NA
これが高速で、まばらで不規則な時間で動作することを望みます。私は、data.table ローリング ジョインがそれをやってくれると思っていました。ただし、ローリング結合は、前回または同じ時間を検出するように見えます。そのため、(コピーの列名に _PREV を追加した後に) 同じテーブルの 2 つのコピーに対してローリング結合を行うと、うまくいきません。コピーの時間変数に小さな数字を追加することでそれをごまかすことができますが、これはちょっと厄介です。
ローリンジョインまたは他のdata.tableメソッドでこれを簡単に行う方法はありますか? 効率的な方法を見つけましたが、それでも約 40 行の R コードが必要です。ローリング ジョインに同じ時刻を含めずに最後の時刻を探すように指示できる場合、これはワンライナーになる可能性があるようです。あるいは、他に巧妙なトリックがあるかもしれません。
サンプルデータはこちら。
data=data.table(customer_id=c(1,2,1,1,2),time_stamp=c(252,632,456,223,455),value=c(1,2,3,4,5))
data_sorted=data[order(customer_id,time_stamp)]
これは私が書いたコードです。customer_id が異なる行に NA を入れる行は警告をスローし、おそらく変更する必要があることに注意してください。以下にコメントアウトしました。これらの2行を置き換えるための提案はありますか?
add_prev_next_cbind<-function(data,ident="customer_id",timecol="time_stamp",prev_tag="PREV",
next_tag="NEXT",sep="_"){
o=order(data[[ident]],data[[timecol]])
uo=order(o)
data=data[o,]
Nrow=nrow(data)
Ncol=ncol(data)
#shift it, put any junk in the first row
data_prev=data[c(1,1:(Nrow-1)),]
#shift it, put any junk in the last row
data_next=data[c(2:(Nrow),Nrow),]
#flag the rows where the identity changes, these get NA
prev_diff=data[[ident]] != data_prev[[ident]]
prev_diff[1]=T
next_diff=data[[ident]] != data_next[[ident]]
next_diff[Nrow]=T
#change names
names=names(data)
names_prev=paste(names,prev_tag,sep=sep)
names_next=paste(names,next_tag,sep=sep)
setnames(data_prev,names,names_prev)
setnames(data_next,names,names_next)
#put NA in rows where prev and next are from a different ident
#replace the next two lines with something else
#data_prev[prev_diff,]<-NA
#data_next[next_diff,]<-NA
data_all=cbind(data,data_prev,data_next)
data_all=data_all[uo,]
return(data_all)
}