更好的方法来按组进行ifelse

时间:2015-11-20 22:20:26

标签: r if-statement group-by data.table

我有ID,重量,日期,状态和基线列的数据集如下

  Id     Weight     Date         Status     Baseline
  5      121.23     04/16/1995   No         NA
  5      134.12     12/17/2008   No         NA
  5      167.63     03/15/2002   No         NA
  5      139.22     08/15/2001   No         NA
  23     232.19     11/10/2009   Yes        11/06/2001
  23     274.13     10/03/2004   Yes        11/06/2001
  23     134.23     07/11/2006   Yes        11/06/2001

如果状态为“否”,则我希望新列 Recent_Weight 为该Id存储最接近SysDate()的权重。如果状态为是,那么我希望 Recent_Weight 是最接近基线列中日期的权重。

  Id     Weight     Date         Status     Baseline      Recent_Weight
  5      121.23     04/16/1995   No         NA            134.12 
  5      134.12     12/17/2008   No         NA            134.12  
  5      167.63     03/15/2002   No         NA            134.12
  5      139.22     08/15/2001   No         NA            134.12
  23     232.19     11/10/2009   Yes        11/06/2001    274.13    
  23     274.13     10/03/2004   Yes        11/06/2001    274.13
  23     134.23     07/11/2006   Yes        11/06/2001    274.13

现在我正在使用mutate和group_by执行此操作,如下所示

library(dplyr)
Test2 %>% 
  group_by(Id) %>% 
  mutate(New_Weight = ifelse(Status== "No",   
  as.numeric(Weight[which.min(abs(Sys.Date() - Date))]), 
  as.numeric(Weight[which.min(abs(Baseline   - Date))])))

但是我的结果非常不一致。我必须每次关机并重新启动,否则我会得到错误的答案(我知道这很奇怪)。我想知道是否有人可以建议我更好的方法来获得相同的结果。谢谢你们。感谢你们的时间。

1 个答案:

答案 0 :(得分:0)

您可以尝试data.table方式:

library(data.table)
library(dplyr)

data <- fread(
"Id     Weight     Date         Status     Baseline
5      121.23     04/16/1995   No         NA
5      134.12     12/17/2008   No         NA
5      167.63     03/15/2002   No         NA
5      139.22     08/15/2001   No         NA
23     232.19     11/10/2009   Yes        11/06/2001
23     274.13     10/03/2004   Yes        11/06/2001
23     134.23     07/11/2006   Yes        11/06/2001"
) %>% mutate(
  Status   = Status=='Yes',
  Date     = as.Date(Date, format="%m/%d/%Y"),
  Baseline = as.Date(Baseline, format="%m/%d/%Y")
)

data[, Recent_Weight := ifelse(Status,
  Weight[which.min(abs(Date-Baseline))],
  Weight[which.max(Date)] # no need to compare to Sys.Date()
                          # if you do not have dates in the future
), by=Id]