在 data.table 文件中创建更高效的循环
make a more efficient loop in data.table file
我正在尝试使用循环对当前 data.table 进行子集化。这个过程非常缓慢。这是子集化之前的数据样本。
# V1 V2 V3 type
#1: 1 362.25 361.75 A
#2: 1 362.25 361.75 B
#3: 3 362.25 361.75 C
#4: 4 362.75 362.00 C
#5: 8 362.50 362.00 A
#6: 6 362.50 362.00 B
#7: 12 362.50 362.89 A
#8: 8 362.25 362.05 B
#9: 9 362.25 362.00 A
#10: 17 362.25 362.20 B
#11: 29 362.25 362.90 C
#12: 41 362.25 362.40 C
#13: 99 362.25 362.10 C
#14: 81 362.25 362.00 C
我想根据变量 "type" 对数据进行子集化。我只想保留所有行 (data$type =="c"
),我还需要 (data$type =="A"
) 和 (data$type =="B"
) 的两行,前提是它们后面跟着 (data$type="C"
) 排。子集化后,数据应如下所示:
# V1 V2 V3 type
#1: 1 362.25 361.75 A
#2: 1 362.25 361.75 B
#3: 3 362.25 361.75 C
#4: 4 362.75 362.00 C
#9: 9 362.25 362.00 A
#10: 17 362.25 362.20 B
#11: 29 362.25 362.90 C
#12: 41 362.25 362.40 C
#13: 99 362.25 362.10 C
#14: 81 362.25 362.00 C
If (data$type == "C"
) 那么该行需要保留。第 #1、#2、#9、#10 行也被保留,因为它们后面跟着 "type==C"
行。
我现在正在使用循环来做,但是速度非常慢。
data$temp<-"omit"
for (j in 3:nrow(data)){
if (data$type[j] == "C" && data$type[j-1] == "B"
&& data$type[j-2] == "A" )
{
data$temp[j] <- "pair" ; data$temp[j-1] <- "pair"; data$temp[j-2] <- "pair"
}
}
for (j in 2:nrow(data)){
if (data$type[j-1] == "C" && data$type[j] == "C"
&& data$temp[j-1] == "pair" && data$temp[j]== "omit")
{
nearby$temp[j] <- "pair"
}
}
data<-data[!(data$temp=="omit"),]
此代码运行良好,但速度太慢。请给我一些提高效率但做同样工作的想法。
非常感谢
您可以使用 which
获取具有 "C" 的行的索引。然后包括小于找到的索引 1 和 2 数字。
例如:
df = data.frame(d = c(1,2,3,4,5,6,7,8,9,0),t = c("A","B","C","C","A","B","A","B","C","C"))
> df
d t
1 1 A
2 2 B
3 3 C
4 4 C
5 5 A
6 6 B
7 7 A
8 8 B
9 9 C
10 0 C
c(which(df$t=="C")
将 return:
[1] 3 4 9 10
但您还想包括第 1、2、7 和 8 行。
然后做:
df[sort(unique(c(which(df$t=="C"),which(df$t=="C")-1,which(df$t=="C")-2))),]
d t
1 1 A
2 2 B
3 3 C
4 4 C
7 7 A
8 8 B
9 9 C
10 0 C
sort
和 unique
将删除重复项,排序将按顺序设置所有索引。
注意:我假设没有像 CAC 或 CBC 这样的序列。这还将包括像 BACC 这样的序列(不检查 A 和 B 的顺序)。
在这种情况下不需要 for
循环。通过使用 data.table
的 shift
函数,您可以按如下方式对数据进行子集化(假设 A
和 B
始终按显示顺序排列):
DT[type=='C' | (type=='A' & shift(type, 2, NA, 'lead')=='C') | (type=='B' & shift(type, 1, NA, 'lead')=='C')]
给出:
V1 V2 V3 type
1: 1 362.25 361.75 A
2: 1 362.25 361.75 B
3: 3 362.25 361.75 C
4: 4 362.75 362.00 C
5: 9 362.25 362.00 A
6: 17 362.25 362.20 B
7: 29 362.25 362.90 C
8: 41 362.25 362.40 C
9: 99 362.25 362.10 C
10: 81 362.25 362.00 C
我正在尝试使用循环对当前 data.table 进行子集化。这个过程非常缓慢。这是子集化之前的数据样本。
# V1 V2 V3 type
#1: 1 362.25 361.75 A
#2: 1 362.25 361.75 B
#3: 3 362.25 361.75 C
#4: 4 362.75 362.00 C
#5: 8 362.50 362.00 A
#6: 6 362.50 362.00 B
#7: 12 362.50 362.89 A
#8: 8 362.25 362.05 B
#9: 9 362.25 362.00 A
#10: 17 362.25 362.20 B
#11: 29 362.25 362.90 C
#12: 41 362.25 362.40 C
#13: 99 362.25 362.10 C
#14: 81 362.25 362.00 C
我想根据变量 "type" 对数据进行子集化。我只想保留所有行 (data$type =="c"
),我还需要 (data$type =="A"
) 和 (data$type =="B"
) 的两行,前提是它们后面跟着 (data$type="C"
) 排。子集化后,数据应如下所示:
# V1 V2 V3 type
#1: 1 362.25 361.75 A
#2: 1 362.25 361.75 B
#3: 3 362.25 361.75 C
#4: 4 362.75 362.00 C
#9: 9 362.25 362.00 A
#10: 17 362.25 362.20 B
#11: 29 362.25 362.90 C
#12: 41 362.25 362.40 C
#13: 99 362.25 362.10 C
#14: 81 362.25 362.00 C
If (data$type == "C"
) 那么该行需要保留。第 #1、#2、#9、#10 行也被保留,因为它们后面跟着 "type==C"
行。
我现在正在使用循环来做,但是速度非常慢。
data$temp<-"omit"
for (j in 3:nrow(data)){
if (data$type[j] == "C" && data$type[j-1] == "B"
&& data$type[j-2] == "A" )
{
data$temp[j] <- "pair" ; data$temp[j-1] <- "pair"; data$temp[j-2] <- "pair"
}
}
for (j in 2:nrow(data)){
if (data$type[j-1] == "C" && data$type[j] == "C"
&& data$temp[j-1] == "pair" && data$temp[j]== "omit")
{
nearby$temp[j] <- "pair"
}
}
data<-data[!(data$temp=="omit"),]
此代码运行良好,但速度太慢。请给我一些提高效率但做同样工作的想法。
非常感谢
您可以使用 which
获取具有 "C" 的行的索引。然后包括小于找到的索引 1 和 2 数字。
例如:
df = data.frame(d = c(1,2,3,4,5,6,7,8,9,0),t = c("A","B","C","C","A","B","A","B","C","C"))
> df
d t
1 1 A
2 2 B
3 3 C
4 4 C
5 5 A
6 6 B
7 7 A
8 8 B
9 9 C
10 0 C
c(which(df$t=="C")
将 return:
[1] 3 4 9 10
但您还想包括第 1、2、7 和 8 行。 然后做:
df[sort(unique(c(which(df$t=="C"),which(df$t=="C")-1,which(df$t=="C")-2))),]
d t
1 1 A
2 2 B
3 3 C
4 4 C
7 7 A
8 8 B
9 9 C
10 0 C
sort
和 unique
将删除重复项,排序将按顺序设置所有索引。
注意:我假设没有像 CAC 或 CBC 这样的序列。这还将包括像 BACC 这样的序列(不检查 A 和 B 的顺序)。
在这种情况下不需要 for
循环。通过使用 data.table
的 shift
函数,您可以按如下方式对数据进行子集化(假设 A
和 B
始终按显示顺序排列):
DT[type=='C' | (type=='A' & shift(type, 2, NA, 'lead')=='C') | (type=='B' & shift(type, 1, NA, 'lead')=='C')]
给出:
V1 V2 V3 type
1: 1 362.25 361.75 A
2: 1 362.25 361.75 B
3: 3 362.25 361.75 C
4: 4 362.75 362.00 C
5: 9 362.25 362.00 A
6: 17 362.25 362.20 B
7: 29 362.25 362.90 C
8: 41 362.25 362.40 C
9: 99 362.25 362.10 C
10: 81 362.25 362.00 C