【问题标题】:for-loop through ID-List & counting Values通过 ID 列表和计数值进行 for 循环
【发布时间】:2018-03-25 19:31:36
【问题描述】:

我希望有人可以帮助我解决我的问题,我知道使用两个 for 循环不是很有效,但这是我的第一个解决方案。我有一个包含眼科患者的数据框(AllPat)(患者 ID、日期和就诊 ->'o'perations 或 'c'heckups)

#Pat    Date        Visit    
#1,l    2015-03-30    c        
#1,l    2015-06-03    o        
#1,l    2015-07-01    o        
#1,l    2015-07-20    c    
#1,l    2016-03-16    o        
#1,l    2016-04-13    o        
#1,l    2016-05-09    c           
#2,l    2014-12-23    c 
#2,l    2015-01-21    o        
#2,l    2015-03-16    c    
#2,l    2015-11-23    o        

我想计算每个患者 ID 的操作块(检查前后)

#Pat    Date        Visit    Block
#1,l    2015-03-30    c        
#1,l    2015-06-03    o        1
#1,l    2015-07-01    o        2
#1,l    2015-07-20    c    
#1,l    2016-03-16    o        1
#1,l    2016-04-13    o        2
#1,l    2016-05-09    c           
#2,l    2014-12-23    c 
#2,l    2015-01-21    o        1
#2,l    2015-03-16    c    
#2,l    2015-11-23    o        1

这就是当前的代码:

for(i in unique(AllPat$Pat)){
op <- 0
for(j in AllPat$Pat){
  if(i == j) {
    if(AllPat$Visit[AllPat$Pat == j] == "o") {
      AllPat$Block[AllPat$Pat == j] <- op
      op <- op+1
    }
    else op<-0
  }
}
}

我的问题是,$Block 中的值只有在我在数据框视图中手动排序时才可见,也许有人有更好的解决方案并且可以帮助我


更新: 我当前的数据框和建议的函数 rleid:

Patient Date    Visit   DiffDate    Block
3,r 16.02.2016  m       0
3,r 16.02.2016  m   0   0
3,r 16.02.2016  m   0   0
3,r 16.02.2016  m   0   0
3,r 20.04.2016  o   64  1
3,r 18.05.2016  o   28  1 <<- should be 2
3,r 15.06.2016  o   28  1 <<- should be 3
3,r 04.07.2016  m   19  0
3,r 27.07.2016  o   23  1
3,r 24.08.2016  o   28  2
3,r 18.10.2016  o   55  3

也许我应该改变我的 difftime 函数? 当前计算块的代码是:

n <- nrow(AllPat)
AllPat<- transform(AllPat, Block = ave(1:n, rleid(Patient, Visit, (DiffDate<= 60)), FUN = seq_along) * (Visit== "o"))

以及日期之间的差异:

setDT(AllPat)[, DiffDate:= difftime(AllPat$Date, shift(AllPat$Date), units = "days"), by = c("Patient")]

更新

4,l 2015-05-18  m   NA  0
4,l 2015-10-20  o   155 1 
4,l 2016-05-31  o   224 2 <<-1
4,l 2016-07-26  o   56  1

【问题讨论】:

    标签: r for-loop if-statement transform


    【解决方案1】:

    data.table 包中的rleid 可以在这里提供帮助。我们使用 0 作为检查块。

    library(data.table)
    AllPatDT <- data.table(AllPat)
    AllPatDT[, Block := ave(.I, rleid(X.Pat, Visit), FUN = seq_along) * (Visit == "o")]
    

    给予:

    > AllPatDT
        X.Pat       Date Visit Block
     1:  #1,l 2015-03-30     c     0
     2:  #1,l 2015-06-03     o     1
     3:  #1,l 2015-07-01     o     2
     4:  #1,l 2015-07-20     c     0
     5:  #1,l 2016-03-16     o     1
     6:  #1,l 2016-04-13     o     2
     7:  #1,l 2016-05-09     c     0
     8:  #2,l 2014-12-23     c     0
     9:  #2,l 2015-01-21     o     1
    10:  #2,l 2015-03-16     c     0
    11:  #2,l 2015-11-23     o     1
    

    如果您更喜欢直接的 data.frame,则仅使用我们提供的 data.table 包中的rleid

    library(data.table)
    
    n <- nrow(AllPat)
    transform(AllPat, Block = ave(1:n, rleid(X.Pat, Visit), FUN = seq_along) * (Visit == "o"))
    

    注意

    我们使用了以下AllPat

    Lines <- "#Pat    Date        Visit    
    #1,l    2015-03-30    c        
    #1,l    2015-06-03    o        
    #1,l    2015-07-01    o        
    #1,l    2015-07-20    c    
    #1,l    2016-03-16    o        
    #1,l    2016-04-13    o        
    #1,l    2016-05-09    c           
    #2,l    2014-12-23    c 
    #2,l    2015-01-21    o        
    #2,l    2015-03-16    c    
    #2,l    2015-11-23    o"
    AllPat <- read.table(text = Lines, header = TRUE, comment.char = "", as.is = TRUE)
    

    【讨论】:

    • 好了。为您的答案添加了一个赞成票,并恢复了正确的顺序。我一直很尴尬,因为我的声望比你的高。
    • 非常感谢您的快速解决方案,我没有解释我只想在 60 天($Days)之间存在差异时将操作计数到 Block,否则计数器会重新开始。因此,我已经写了一个新列,其中包含两个日期之间的天数差异(从 2 行开始),我没有在第一个问题中解释它,因为我相信我以后可以用这个额外的条件扩展 for 循环,这显然是从一开始就不是正确的方式
    • 添加一列 d 给出自最后一行以来的天数差异,然后使用 rleid(X.Pat, Visit, cumsum(d &lt;= 60)) 或者您可能想要 > 而不是
    • 更新的最后 2 行之间的间隔不到 60 天,因此在您的示例中 Block 的最后一个值应该是 2,而不是 1,并且经过更正,我在 cmets 中的建议确实有效。 AllPatDT[, Block := ave(.I, rleid(X.Pat, Visit, cumsum(c(0, diff(as.Date(Date))) &gt;= 60)), FUN = seq_along) * (Visit == "o")]
    • seq_along 替换为function(x) c(0 * x, 1)[-1]length
    【解决方案2】:

    我搜索了“组内的[r] 序列”,并找到了一个答案,我能够用我拥有的一个技巧(老实说,可能是从 G.Grothendieck 学到的)来适应组的答案。这是 Martin Morgan(经过认证的 R 大师)的答案的链接

    generate sequence (and starting over in case of a recurrence) and add new column with highest number per sequence, within group, in R

    我将这一点添加到我的技巧中,即在条件发生的点形成组:

    > dat$seq <- cumsum(dat$Visit=="c")
    > dat
       Pat       Date Visit seq
    1  1,l 2015-03-30     c   1
    2  1,l 2015-06-03     o   1
    3  1,l 2015-07-01     o   1
    4  1,l 2015-07-20     c   2
    5  1,l 2016-03-16     o   2
    6  1,l 2016-04-13     o   2
    7  1,l 2016-05-09     c   3
    8  2,l 2014-12-23     c   4
    9  2,l 2015-01-21     o   4
    10 2,l 2015-03-16     c   5
    11 2,l 2015-11-23     o   5
    > rle <- rle(paste(dat$Pat, dat$seq, sep = "\r"))
    > dat$Seq <- unlist(lapply(rle$length, seq_len))
    > dat
       Pat       Date Visit seq Seq
    1  1,l 2015-03-30     c   1   1
    2  1,l 2015-06-03     o   1   2
    3  1,l 2015-07-01     o   1   3
    4  1,l 2015-07-20     c   2   1
    5  1,l 2016-03-16     o   2   2
    6  1,l 2016-04-13     o   2   3
    7  1,l 2016-05-09     c   3   1
    8  2,l 2014-12-23     c   4   1
    9  2,l 2015-01-21     o   4   2
    10 2,l 2015-03-16     c   5   1
    11 2,l 2015-11-23     o   5   2
    > rle <- rle(paste(dat$Pat, dat$seq, sep = "\r"))
    > dat$Seq <- dat$Seq -1
    > dat$Seq[dat$Seq==0] <- " "
    > dat
       Pat       Date Visit seq Seq
    1  1,l 2015-03-30     c   1    
    2  1,l 2015-06-03     o   1   1
    3  1,l 2015-07-01     o   1   2
    4  1,l 2015-07-20     c   2    
    5  1,l 2016-03-16     o   2   1
    6  1,l 2016-04-13     o   2   2
    7  1,l 2016-05-09     c   3    
    8  2,l 2014-12-23     c   4    
    9  2,l 2015-01-21     o   4   1
    10 2,l 2015-03-16     c   5    
    11 2,l 2015-11-23     o   5   1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-22
      • 2021-03-29
      • 2018-10-18
      • 2018-07-18
      • 1970-01-01
      • 1970-01-01
      • 2023-03-14
      • 1970-01-01
      相关资源
      最近更新 更多