【问题标题】:Better approach to doing ifelse by group按组进行 ifelse 的更好方法
【发布时间】:2015-11-20 22:20:25
【问题描述】:

我的数据集包含 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))])))

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

【问题讨论】:

  • 似乎data.tablepackage 可能非常适合?我知道它的语法非常适合这些条件修改。
  • $Status == "No" 时,您将Sys.Date() 与哪个领域进行比较?同样,你在哪里定义DATE
  • @r2evans,我的错,我现在解决了这个问题。 Status == "No" 比较 Sys.Date() 与 Date 列中的日期,并在此示例中选择最接近 Sys.Date() 的权重,12/17/2008 因此 New_Weight 为 134.12
  • 我让您的代码按要求工作,但 (1) 字符串作为日期存在问题,因此我使用 mutate(Date=as.POSIXct(Date, format="%m/%d/%Y", tz="UTC"), Baseline=<similar>) 进行转换,并且 (2) 将 DATE 替换为 Date。如果您得到不一致的结果,请举例说明它是如何变化的。 (顺便说一句:如果您的 Dates 是因素,那么这也不会达到您想要的效果,尽管您应该收到有关此效果的警告。)
  • @r2evans,是的,日期应该是这项工作的日期格式,你就在那里,但我看到的结果在某种意义上不一致,我需要运行一次并关闭 RStudio 并重新开始,如果我在一个会话中多次运行它,那么从第二次迭代开始,我一直将所有内容(New_Weight)都视为 134.12...它不会根据Status=="Yes" 和基线日期标准而改变。我喜欢在 data.table 中看到这一点,就像上面建议的 @Alex 一样。

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


【解决方案1】:

你可以试试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]

【讨论】:

  • 物有所值,这比使用 dplyr 和 mutate 要好得多。 +10 人。
猜你喜欢
  • 2011-07-22
  • 2016-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-28
  • 1970-01-01
  • 2015-06-17
  • 2011-02-01
相关资源
最近更新 更多