[英]How to optimize lagged differences in data.table (r)
我正在嘗試使用R中的data.table來優化一段r代碼以計算滯后差異。我有兩個工作解決方案,但兩者都在我的真實數據(5億行數據集)上運行緩慢。 我一般都喜歡使用data.table的加速和效率,但我實現的兩個解決方案都很慢(與其他data.table操作相比)。
任何人都可以為data -table提供更高效的編碼實踐建議嗎?
library(data.table)
set.seed(1)
id <- 1:10
date_samp <- seq.Date(as.Date("2010-01-01"),as.Date("2011-01-01"),"days")
dt1 <-
data.table(id = sample(id,size = 30,replace=T),
date_1 = sample(date_samp,size = 30,replace=T))
setkey(dt1,id,date_1)
### Attempt to get lagged date
## Attempt 1
dt1[,date_diff:=c(0,diff(date_1)),
by=id]
## Attempt 2
## Works but gives warnings
dt1[,date_diff:=NULL]
dt1[,n_group := .N,by=id]
dt1[,date_diff:=c(0,date_1[2:n_group]-date_1[1:(n_group-1)]),
by=id]
經過一番努力后,我在相關問題上找到了“shift()”函數。 我已經使數據更大並進行了一些粗略的分析,並添加了一些更多的方法......但如果有更有效的方法,請更新並提供不同的答案。
在回復下面的評論時,我添加並更改了一些內容...嘗試是數字(不是整數),而我的鍵入是不正確的。 我添加了一個整數比較和一個鍵入的整數(除了數字)。 現在看起來像將日期轉換為整數然后使用“按每個i分組”是最快的解決方案。
library(data.table)
set.seed(1)
id <- 1:100
date_samp <- seq.Date(as.Date("2010-01-01"),as.Date("2011-01-01"),"days")
n_samp <- 1e7
dt1 <-
data.table(id = sample(id,size = n_samp,replace=T),
date_1 = sample(date_samp,size = n_samp,replace=T))
setkey(dt1,id,date_1)
### Attempt to get lagged date
## Attempt 1
dt1[,date_diff:=NULL]
system.time(dt1[,date_diff:=c(0,diff(date_1)),
by=id])
## Attempt 2
dt1[,date_diff:=NULL]
dt1[,n_group := .N,by=id]
system.time(dt1[,date_diff:=c(0,date_1[2:n_group]-date_1[1:(n_group-1)]),
by=id])
## Attempt 3
dt1[,date_diff:=NULL]
system.time(dt1[,date_diff:=date_1-shift(date_1),
by=id])
## Attempt 4
## Use numeric instead
dt1[,date_diff:=NULL]
dt1[,date_1num:=NULL]
dt1[,date_1num:=as.numeric(date_1)]
system.time(dt1[,date_diff:=date_1num-shift(date_1num),
by=id])
## Attempt 5
## Use a keyed by
dt_key <- unique(dt1[,list(id)])
dt1[,date_diff:=NULL]
system.time(dt1[dt_key,
date_diff:=date_1num-shift(date_1num),
by=.EACHI])
## Attempt 6
## Use integers instead
dt1[,date_diff:=NULL]
dt1[,date_1int:=as.integer(date_1)]
system.time(dt1[,date_diff:=date_1int-shift(date_1int),
by=id])
## Attempt 7
## Use integers with keyed by
dt1[,date_diff:=NULL]
dt1[,date_1int:=as.integer(date_1)]
system.time(dt1[dt_key,
date_diff:=date_1int-shift(date_1int),
by=.EACHI])
# attempt user system elapsed
# 1 0.34 0.25 0.59
# 2 0.37 0.28 0.67
# 3 0.25 0.16 0.41
# 4 0.11 0.01 0.13
# 5 0.06 0.03 0.10
# 6 0.09 0.00 0.09
# 7 0.05 0.00 0.04
如果你想要修改:
dt1[order(id, date_1)
][, idP := shift(id, type='lag')
][, headP := is.na(idP) | idP != id
][, date_1P := shift(date_1, type='lag')
][headP == T, date_diff := 0
][headP == F, date_diff := date_1 - date_1P
][, c('headP', 'idP', 'date_1P') := NULL
][]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.