使用 data.table 索引序列块
Indexing sequence chunks using data.table
假设我有一个数据集,其中长度为 1 的序列是非法的,长度为 2 的序列是合法的,长度大于 5 的序列是非法的,但允许将较长的序列分成 <=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 交替设置。
非常感谢任何指导。
如果我对你的问题理解正确,你想在 R == 0
或 R == 1 & (1 =< Seq < 6 | Seq > 6)
时将 fix_min
设置为 FALSE
。然后下面应该给你你想要的:
# recreating the data from your first code block
set.seed(1)
DT1 <- data.table(R=sample(0:1, 20000, rep=TRUE))[, smp:=.I
][, Seq:=seq(.N), by=rleid(R)
][, Seq2 := Seq[.N], by=rleid(R)]
# adding the needed 'fix_min' column
DT1[, fix_min := (R==1 & Seq[.N] > 1 & Seq%%6!=0), by=rleid(R)
][R==1 & Seq%%6==1 & Seq2%%6==1 & Seq==Seq2, fix_min := FALSE]
解释:
data.table(R=sample(0:1, 20000, rep=TRUE))
创建 data.table 的基础
[, smp:=.I]
创建一个索引并将其添加到 data.table
by=rleid(R)
标识序列;看看它做了什么尝试:data.table(R=sample(0:1, 20000, rep=TRUE))[, seq.id:=rleid(R)]
[, Seq:=seq(.N), by=rleid(R)]
为每个序列创建一个索引并将其添加到 data.table;序列由 rleid(R)
标识
[, Seq2 := Seq[.N], by=rleid(R)]
创建一个变量,其中包含一个指示序列长度的值
fix_min := (R==1 & Seq[.N] > 1 & Seq%%6!=0)
创建一个具有 TRUE
值的逻辑向量,其中 R==1
& 序列的长度大于 1 (Seq[.N] > 1
),不包括序列所在的值数字是 6
(Seq%%6!=0
) 的倍数
R==1 & Seq%%6==1 & Seq2%%6==1 & Seq==Seq2
按如下方式过滤 data.table:仅包含 R==1
且序列值为 7
的行,13
, 19
, etc (Seq%%6==1
) & 序列的长度为 7
, 13
, 19
, etc 只选择最后一个从满足其他条件的序列中提取行 (Seq==Seq2
)。使用 fix_min := FALSE
,您将它们设置为 FALSE
。
假设我有一个数据集,其中长度为 1 的序列是非法的,长度为 2 的序列是合法的,长度大于 5 的序列是非法的,但允许将较长的序列分成 <=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 交替设置。
非常感谢任何指导。
如果我对你的问题理解正确,你想在 R == 0
或 R == 1 & (1 =< Seq < 6 | Seq > 6)
时将 fix_min
设置为 FALSE
。然后下面应该给你你想要的:
# recreating the data from your first code block
set.seed(1)
DT1 <- data.table(R=sample(0:1, 20000, rep=TRUE))[, smp:=.I
][, Seq:=seq(.N), by=rleid(R)
][, Seq2 := Seq[.N], by=rleid(R)]
# adding the needed 'fix_min' column
DT1[, fix_min := (R==1 & Seq[.N] > 1 & Seq%%6!=0), by=rleid(R)
][R==1 & Seq%%6==1 & Seq2%%6==1 & Seq==Seq2, fix_min := FALSE]
解释:
data.table(R=sample(0:1, 20000, rep=TRUE))
创建 data.table 的基础
[, smp:=.I]
创建一个索引并将其添加到 data.tableby=rleid(R)
标识序列;看看它做了什么尝试:data.table(R=sample(0:1, 20000, rep=TRUE))[, seq.id:=rleid(R)]
[, Seq:=seq(.N), by=rleid(R)]
为每个序列创建一个索引并将其添加到 data.table;序列由rleid(R)
标识
[, Seq2 := Seq[.N], by=rleid(R)]
创建一个变量,其中包含一个指示序列长度的值fix_min := (R==1 & Seq[.N] > 1 & Seq%%6!=0)
创建一个具有TRUE
值的逻辑向量,其中R==1
& 序列的长度大于 1 (Seq[.N] > 1
),不包括序列所在的值数字是6
(Seq%%6!=0
) 的倍数
R==1 & Seq%%6==1 & Seq2%%6==1 & Seq==Seq2
按如下方式过滤 data.table:仅包含R==1
且序列值为7
的行,13
,19
, etc (Seq%%6==1
) & 序列的长度为7
,13
,19
, etc 只选择最后一个从满足其他条件的序列中提取行 (Seq==Seq2
)。使用fix_min := FALSE
,您将它们设置为FALSE
。