在R中找到最接近的两周日期

时间:2016-04-06 15:27:19

标签: r date lubridate

哥伦比亚的工资(大部分)是每两周支付一次,即每月的第15天和最后一天。我试图从销售日期开始生成一个新变量,我希望与销售量高度相关:自上次付款日起的天数,我能否一旦我有了付款日期,就算一个简单的差异。

我有一个销售数据框a,其日期来自我们只关心销售日期,如下所示:

structure(list(date = structure(c(1423121832, 1423988603, 1424779384, 
1425132001, 1427800333), tzone = "UTC", class = c("POSIXct", 
"POSIXt"))), .Names = "date", row.names = c(NA, -5L), class = "data.frame")

我想为每个日期生成最接近付款日的向量,但无法处理每个月的结尾。我通过以下方式解决了其余问题:

library(lubridate)
cbind(a, 
      basedate = as.Date(
                   ifelse(day(a$date) %in% c(15:31), 
                          floor_date(a$date, "month")+(3600*24*14), 
                          floor_date(a$date, "month") - (3600 * 24)) / (3600 * 24), 
                   origin = origin))

从我得到:

                 date   basedate
1 2015-02-05 07:37:12 2015-01-31
2 2015-02-15 08:23:23 2015-02-15
3 2015-02-24 12:03:04 2015-02-15
4 2015-02-28 14:00:01 2015-02-15
5 2015-03-31 11:12:13 2015-03-15

第4行和第5行中的基础向量不正确。我希望最后两个basedate&#39}为2015-02-282015-03-31。我知道我可以通过在我的代码中嵌套另一个ifelse来获得它,但我很确定 简单方法,而我还没有遇到它

如何正确确定距离最近的两周(付费日)? (我更喜欢baselubridate解决方案。但欢迎处理此问题的任何其他包。

1 个答案:

答案 0 :(得分:1)

使用lubridate,您可以创建一个索引,指示当前月份的第14天和前几天的天数。使用该索引,找到最后一个发薪日。最后,您可以计算paydate和当前日期之间的差异:

library(lubridate)
d <- as.Date(df$date)
islastday <- d == (ceiling_date(d, unit="month") - 1)
isbefore15 <- as.integer(format(df$date, '%e'))/15 < 1L
payday <- Sys.Date()
for(i in 1:length(d)) {
  payday[i] <- if(islastday[i]) {
              d[i]
  } else if(isbefore15[i]) {
    floor_date(d[i], unit="month") - 1L

  } else {  floor_date(d[i], unit="month") + 14L 

  }
}

df$payday <- payday
df$difference <- as.Date(df$date) - df$payday
df
#                  date     payday difference
# 1 2015-02-05 07:37:12 2015-01-31     5 days
# 2 2015-02-15 08:23:23 2015-02-15     0 days
# 3 2015-02-24 12:03:04 2015-02-15     9 days
# 4 2015-02-28 14:00:01 2015-02-28     0 days
# 5 2015-03-31 11:12:13 2015-03-31     0 days

<强>更新

更快的解决方案:

d2 <- d
d2[isbefore15] <- floor_date(d[isbefore15], unit="month") - 1L
d2[!isbefore15] <- floor_date(d[!isbefore15], unit="month") + 14L 
df$payday <- d2
df$difference <- as.Date(df$date) - df$payday