【发布时间】:2023-12-17 03:03:01
【问题描述】:
假设我有一个数据集,其中长度为 1 的序列是非法的,长度为 2 的序列是合法的,大于长度 5 的序列是非法的,但允许将较长的序列分解为
set.seed(1)
DT1 <- data.table(smp = 1, R=sample(0:1, 20000, rep=TRUE), Seq = 0L)
DT1[, smp:=1:length(smp)]
DT1[, Seq:=seq(.N), by=list(cumsum(c(0, abs(diff(R)))))]
最后一行直接来自: Creating a sequence in a data.table depending on a column
DT1[, fix_min:=ifelse((R==TRUE & Seq==1) | (R==FALSE), FALSE, TRUE)]
fixmin_idx2 <- which(DT1[, fix_min==TRUE])
DT1[fixmin_idx2 -1, fix_min:=TRUE]
现在我的长度为 2 的合法标记已正确标记。打破>5s。
DT1[R==1 & Seq==6, fix_min:=FALSE]
DT1[,Seq2:=seq(.N), by=list(cumsum(c(0, abs(diff(fix_min)))))]
DT1[R==1 & Seq2==6, fix_min:=FALSE]
fixSeq2_idx7 <- which(DT1[,fix_min==TRUE] & DT1[,Seq2==7])
fixSeq2_idx7
[1] 10203 13228
DT1[fixSeq2_idx7,]
smp R Seq fix_min Seq2
1: 10203 1 13 TRUE 7
2: 13228 1 13 TRUE 7
DT1[fixSeq2_idx7 + 1,]
smp R Seq fix_min Seq2
1: 10204 1 14 TRUE 8
2: 13229 0 1 FALSE 1
现在来测试一个 Seq2==7 后面是否跟着一个 Seq2==8,这将是一个合法的 2 长度。我是一个 7,然后是一个 8,一个不是一个 8。我被卡住了。我尝试过的所有操作要么将所有 fix_min 设置为 TRUE,要么将 TRUE 和 FALSE 交替设置。
非常感谢任何指导。
【问题讨论】:
-
次要修复:
ifelse((R==TRUE & Seq==1) | (R==FALSE), FALSE, TRUE)应该只是!(R==1 & Seq==1)。请注意,R是 0/1 而不是 FALSE/TRUE。在其他地方,我强烈怀疑您不需要这么多括号。例如,在by=中,您不需要将单个向量包装在list()中。 -
不确定,但这是否满足您的期望?
DT1[, if (.N > 1L) .SD[rep(seq_len(min(.N, 5L)), length.out=.N)], by=.(rleid(R), R)]。它删除了Seq只是1的行,如果1:9将其更改为1:5, 1:4.. 这将在您的第一个代码块之后执行。 -
@Arun - 是的,只是此时我不想删除数据中的行,因为非法数据代表了数据中另一个感兴趣的条件。
-
在这种情况下,使用
:=代替.SD并通过检查适当的条件来更新Seq。我认为从之前的评论中可以很简单地理解逻辑? -
@Arun - 我会按照你的建议处理它,但我想我也会挠头。
标签: r indexing data.table sequence chunks