【问题标题】:make a more efficient loop in data.table file在 data.table 文件中进行更有效的循环
【发布时间】:2016-04-28 05:44:22
【问题描述】:

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

我想根据变量“类型”对数据进行子集化。我只想保留 (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"),]

这段代码运行良好,但是太慢了。请给我一些提高效率但做同样工作的想法。

非常感谢

【问题讨论】:

  • 请不要添加将您的代码标记为 html 或 javascript 的行;它弄乱了显示。
  • 感谢@Frank 的建议

标签: r data.table subset


【解决方案1】:

在这种情况下不需要for-loop。使用data.tableshift 函数,您可以按如下方式对数据进行子集化(假设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

【讨论】:

    【解决方案2】:

    您可以使用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") 将返回:

    [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
    

    sortunique 将删除重复,排序将按顺序设置所有索引。

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

    【讨论】:

    • 您对序列的看法是正确的。代码进展顺利。谢谢
    猜你喜欢
    • 1970-01-01
    • 2018-06-18
    • 2014-03-08
    • 1970-01-01
    • 2019-11-26
    • 2015-01-24
    • 2014-10-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多