我有一个带有id列和多列的R data.table,指定有序的阈值级别和相应的值.我想要做的是查找第一级的每一行,该行大于或等于该id的参数并返回相应的值.
这是一个示例数据集.
DT<-data.table(id=c("Obs1","Obs2"),
level.1=c(1,1),level.2=c(2,4),level.3=c(3,8),
val.1=c(10,10),val.2=c(20,30),val.3=c(30,50))
DT
id level.1 level.2 level.3 val.1 val.2 val.3
1: Obs1 1 2 3 10 20 30
2: Obs2 1 4 8 10 30 50
Run Code Online (Sandbox Code Playgroud)
所以如果查找参数:
params<-list("Obs1"=2.5,"Obs2"=1)
Run Code Online (Sandbox Code Playgroud)
返回的值应为:
c(30,10).
Run Code Online (Sandbox Code Playgroud)
我还希望级别和值的数量有些随意,尽管它们将满足类似于示例的命名约定
我可以使用几个步骤来解决这个问题,但它非常难看并且计算效率可能不高:
level.names<-colnames(DT)[grep("level",colnames(DT))]
val.names<-colnames(DT)[grep("val",colnames(DT))]
setkey(DT,id)
idx<-DT[,grep(TRUE,lapply(.SD,function(y)((params[[id]] <= y))))[1],
.SDcols=level.names,by=id]
values<-ifelse(is.na(idx$V1),as.numeric(NA),DT[,get(val.names[idx[id,V1]]),by=id]$V1)
Run Code Online (Sandbox Code Playgroud)
我之前使用plyr :: ddply更清晰地使用data.frames解决了这个问题,并且我可以在data.frame中使用变量名称这一事实.(为简洁起见,我不在此处包含该解决方案.)
欢迎提出任何改进建议.
我使用滚动连接如下所示:
DT_m = melt(DT, measure=patterns("^level", "^val"), value.name=c("level", "val"))
query = list(id=c("Obs1", "Obs2"), level=c(2.5, 1))
DT_m[query, val, on=c("id", "level"), roll=-Inf]
Run Code Online (Sandbox Code Playgroud)
roll=-Inf执行NOCB连接(后向观察向后进行).当通过(此处query)加入的值落入间隙时,下一个观察结果作为匹配行向后传送.例如,2.5介于2和之间4.因此匹配行4(下一次观察).相应的val是30.