談到我的意見變成一個答案,如果你使用data.table
你可以做
setDT(ddf)[order(-time) , copies := rleid(time) ]
ddf <- ddf[rep(1:.N, copies)][, copies:=NULL]
ddf
# time id val1 val2
# 1: 1 a -0.6264538 -0.6264538
# 2: 1 a -0.6264538 -0.6264538
# 3: 1 a -0.6264538 -0.6264538
# 4: 1 a -0.6264538 -0.6264538
# 5: 1 a -0.6264538 -0.6264538
# ---
# 1046: 18 e -0.5732654 4.0950292
# 1047: 18 e -0.5732654 4.0950292
# 1048: 19 e -1.2246126 2.8704166
# 1049: 19 e -1.2246126 2.8704166
# 1050: 20 e -0.4734006 2.3970160
## quick check
table(ddf$time)
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
# 100 95 90 85 80 75 70 65 60 55 50 45 40 35 30 25 20 15 10 5
說明
運行長度編碼(RLE)?rle
(或?data.table::rleid
)
計算向量中等值運行的長度和值
這意味着它將相同的值按順序排列。由於所需的「複製」取決於time
,因此我們可以在order
時間內將數據中相同的值放在一起。
rle
然後從1
編碼相等的值成順序組,則我們可以使用那些組識別爲副本,我們要求各組的數目。
速度比較
正如你更快的速度後,這裏是一個比較原始的和Map
解決方案
fun_orig <- function(x){
ddfz <- do.call('rbind', Map(cbind, ddfx, ival = 1:length(unique(ddf$time))))
return(ddfz)
}
fun_map <- function(x){
df <- Map(function(x,y) x[x$time <= y,], list(ddf), 20:1)
return(df)
}
fun_dt <- function(x){
setDT(ddf)[order(-time) , copies := rleid(time) ]
ddf <- ddf[rep(1:.N, copies)][, copies:=NULL][]
return(ddf)
}
library(microbenchmark)
microbenchmark(fun_orig(ddf), fun_map(ddf), fun_dt(ddf))
# Unit: microseconds
# expr min lq mean median uq max neval cld
# fun_orig(ddf) 4396.559 4547.975 4883.709 4646.162 4784.530 8002.254 100 c
# fun_map(ddf) 3341.207 3497.490 3651.714 3588.343 3649.953 6799.140 100 b
# fun_dt(ddf) 862.612 955.883 1030.185 998.363 1038.336 3850.275 100 a
或'地圖(函數(X,Y)×X (data.table); $ time <= y,],list(ddf),20:1)'data.table'愛好者的' – thelatemail
。 setDT(ddf)[order(-time),copies:= rleid(time)]; ddf < - ddf [rep(1:.N,copies)] [,copies:= NULL]' – tospig
需要確定這些實際上是日期時間值。由於不理解R類,找到字符值(或因子類)並不令人驚訝。 (如果它正常工作,這看起來像一個相當簡單的解決方案。) –