r data.frame 回溯日期

r data.frame going back dates

我有一个 R data.frame 如下。通过商店,我想创建 newstart 和 newend 列,这样 newstart 和 newend 将从各自的开始和结束列中减去 14 天。

但是,如果新开始或新结束日期在原始开始或结束列中,那么我想再往后回溯 14 天。

因此在第 3 行的情况下,newstart 和 newend 将分别为 20131120 和 20131127。但是由于 20131120 出现在商店 8(第 2 行)的末尾列中,我必须再返回 2 周才能获得 newend 和 newstart。我必须再次检查以确保开始和结束列中的商店 8 不存在 newstart 和 newend。我怎么能这样做?

我有一个 table 存储列有多个值。我只是在这里展示一个快照

   store=c(rep(8,4),rep(11,4))
start=c("20131009","20131113","20131204","20150624","20140820","20140924","20150923","20151014")
end=c("20131016","20131120","20131211","20150701","20140827","20141001","20150930","20151021")

maint=data.frame(store,start,end)



maint$start=as.Date(maint$start,"%Y%m%d")
maint$end=as.Date(maint$end,"%Y%m%d")
maint
  store    start      end
1     8 20131009 20131016
2     8 20131113 20131120
3     8 20131204 20131211
4     8 20150624 20150701
5    11 20140820 20140827
6    11 20140924 20141001
7    11 20150923 20150930
8    11 20151014 20151021

--------------------更新1

下面的第一个答案有效。但是在第二行和第三行以及最后两行的情况下,它提供了重叠的日期。我如何在确保 newstart 和 newend 中的日期不与开始和结束列重叠的同时避免这种重叠

  store  start  end newstart    newend

8   10/9/2013   10/16/2013  9/25/2013   10/2/2013
**8 11/13/2013  11/20/2013  10/30/2013  11/6/2013
8   12/4/2013   12/11/2013  10/23/2013  10/30/2013**
8   6/24/2015   7/1/2015    6/10/2015   6/17/2015
11  8/20/2014   8/27/2014   8/6/2014    8/13/2014
11  9/24/2014   10/1/2014   9/10/2014   9/17/2014
**11    9/23/2015   9/30/2015   9/9/2015    9/16/2015
11  10/14/2015  10/21/2015  9/2/2015    9/9/2015**

您可以在 for 循环中使用 while 循环,如下所示

# create newdate columns
maint$newstart <- as.Date(NA)
maint$newend <- as.Date(NA)

# loop over each row of maint
for(i in 1:nrow(maint)) {

  # get all start and end dates for current store
  dates_focal <- c(maint$start[maint$store == maint$store[i]],
                   maint$end[maint$store == maint$store[i]])

  # subtract 14 days from newstart and newend
  newstart <- maint$start[i] - 14
  newend <- maint$end[i] - 14

  # exit condition for following while loop
  exit_condition <- F

  # check for conflict
  # if conflict, repeatedly subtract 14 days until no more conflict
  while(!exit_condition) {

    conflict <- any(is.element(c(newstart, newend), dates_focal))

    if (conflict) {
      newstart <- newstart - 14
      newend <- newend - 14
    } else {
      exit_condition <- T
    }
  }

  # set newstart and newend
  maint$newstart[i] <- as.Date(newstart)
  maint$newend[i] <- as.Date(newend)
}

请注意,此示例不会检查 newstart 和 newend 列中给定商店的冲突。也就是说,给定的商店可能具有重叠的新开始日期和新结束日期(在不同的行中)。如果您的应用程序不希望这样做,应该进行快速修改。

更新 1

如果您还想检查 newstart 和 newend 列是否有冲突,只需将这些列添加到 dates_focal,如:

dates_focal <- c(
  maint$start[maint$store == maint$store[i]],
  maint$end[maint$store == maint$store[i]],
  maint$newstart[maint$store == maint$store[i]],
  maint$newend[maint$store == maint$store[i]]
)

请记住,如果更改维护数据框中的行顺序,此方法可能会产生不同的结果,因为给定行中的新日期取决于之前行中的新日期。