【问题标题】:Iterating over Dates by Group in R using FOR loops使用 FOR 循环在 R 中按组迭代日期
【发布时间】:2020-05-05 12:16:30
【问题描述】:

我正在尝试根据“ExpectedDate”和“ObservedDate”填充“FinalDate”。

规则是:对于每个组,如果观察日期大于上一个预期日期并且小于下一个预期日期,则最终日期等于观察日期,否则最终日期等于预期日期。

如何修改以下代码以确保:

  • FinalDate 由 Group 填写
  • 迭代次数不会跳过任何行
set.seed(2)
dat<-data.frame(Group=sample(LETTERS[1:10], 100, replace=TRUE), 
                Date=sample(seq(as.Date('2013/01/01'), as.Date('2020/01/01'), by="day"), 100))%>%
  mutate(ExpectedDate=Date+sample(10:200, 100, replace=TRUE),
         ObservedDate=Date+sample(10:200, 100, replace=TRUE))%>%
           group_by(Group)%>%
           arrange(Date)%>%
           mutate(n=row_number())%>%arrange(Group)%>%ungroup()%>%
  as.data.frame()

#generate some missing values in "ObservedDate"
dat[sample(nrow(dat),20), "ObservedDate"]<-NA

dat$FinalDate<-NA
for (i in 1:nrow(dat)){
  dat[i, "FinalDate"]<-if_else(!is.na(dat$"ObservedDate")[i] && 
                                 dat[i, "ObservedDate"] > dat[i-1, "ExpectedDate"] && 
                                 dat[i, "ObservedDate"] < dat[i+1, "ExpectedDate"],
                               dat[i, "ObservedDate"],
                               dat[i,"ExpectedDate"])
}
dat$FinalDate<-as.Date(dat$FinalDate) # convert numeric to Date format

例如在下面的输出中:

在 i=90 时,代码在字母 I 中查找先前的 ExpectedDate

我们希望它仅在字母 J 内查找 ExpectedDate。如果组之前没有预期日期并且 ObservedDate 大于 ExpectedDate 但小于下一个 ExpectedDate,则 FinalDate 应填写 ExpectedDate。

在 i=100 时,代码生成 NA,因为没有可用的下一个观察值

我们希望填充此值,以便对于每个组中的最后一次观察,如果 ObservedDate 大于组内的最后一个 ExpectedDate,则 FinalDate=ObservedDate,否则为 ExpectedDate。

    Group       Date ExpectedDate ObservedDate  n  FinalDate
88      I 2015-09-07   2015-12-05         <NA>  7 2015-12-05
89      I 2018-08-02   2018-11-01   2018-08-13  8 2018-11-01
90      J 2013-07-24   2013-08-30   2013-08-12  1 2013-08-30
91      J 2013-11-22   2014-01-02   2014-04-05  2 2014-04-05
92      J 2014-11-03   2015-03-23   2015-05-10  3 2015-05-10
93      J 2015-08-30   2015-12-09   2016-02-04  4 2016-02-04
94      J 2016-04-18   2016-09-03         <NA>  5 2016-09-03
95      J 2016-10-10   2017-01-29   2017-04-14  6 2017-04-14
96      J 2017-02-14   2017-07-05         <NA>  7 2017-07-05
97      J 2017-04-21   2017-10-01   2017-08-26  8 2017-08-26
98      J 2017-10-01   2018-01-27   2018-02-28  9 2018-02-28
99      J 2018-08-03   2019-01-31   2018-10-20 10 2018-10-20
100     J 2019-04-25   2019-06-23   2019-08-16 11       <NA>

【问题讨论】:

标签: r loops dplyr nested purrr


【解决方案1】:

我们可以放开for 循环并使用group_bylaglead 这里来自dplyr

library(dplyr)

dat %>%
  group_by(Group) %>%
  mutate(FinalDate = if_else(ObservedDate > lag(ExpectedDate) & 
                    ObservedDate < lead(ExpectedDate), ObservedDate, ExpectedDate)) 

我们也可以这样做data.table::between

dat %>%
  group_by(Group) %>%
  mutate(FinalDate = if_else(data.table::between(ObservedDate, 
           lag(ExpectedDate), lead(ExpectedDate)), ObservedDate, ExpectedDate)) 

【讨论】:

  • Error in data.table::between(ObservedDate, lag(ExpectedDate), lead(ExpectedDate)) : Not yet implemented NAbounds=TRUE for this non-numeric and non-character type 你不能在这里使用data.table::between
  • @M-- 对于 OP 生成的数据,我可以正常工作,并提供与 dplyr 相同的输出。
猜你喜欢
  • 1970-01-01
  • 2021-12-20
  • 2020-09-20
  • 2020-11-25
  • 1970-01-01
  • 1970-01-01
  • 2015-07-25
  • 1970-01-01
  • 2019-10-08
相关资源
最近更新 更多