谈到我的意见变成一个答案,如果你使用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类,找到字符值(或因子类)并不令人惊讶。 (如果它正常工作,这看起来像一个相当简单的解决方案。) –