在data.table文件中创建一个更有效的循环

时间:2016-04-28 05:44:22

标签: r data.table subset

我正在尝试使用循环对当前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

如果(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"),]

此代码工作正常,但速度太慢。请给我一些提高效率的想法,但也要做同样的工作。

非常感谢

2 个答案:

答案 0 :(得分:3)

在这种情况下,不需要for - 循环。使用shift - data.table的函数,您可以按如下方式对数据进行子集化(假设AB始终处于显示的顺序中):

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

答案 1 :(得分:1)

您可以使用#track获取具有&#34; C&#34;的行的索引。然后包括索引1和2的数字少于找到的数字。

例如:

which

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")

但您还想要包含第1,2,7和8行。 然后做:

[1]  3  4  9 10

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将删除重复,排序将按顺序设置所有索引。

注意:我假设没有像CAC或CBC这样的序列。这也将包括像BACC这样的序列(不检查A和B的顺序)。

相关问题