【问题标题】:Match Days of the Week within an Interval to Create Specific Dates在间隔内匹配星期几以创建特定日期
【发布时间】:2018-08-19 15:39:30
【问题描述】:

我正在使用具有以下日期结构的数据集:

Week  DateStart    DateEnd      Day
1     5-Aug-16     11-Aug-16    Monday
2     12-Aug-16    18-Aug-16    Thursday

其中“Week”对应于研究周数,“DateStart”和“DateEnd”是该周的第一天和最后一天,“Day”表示该周内的特定日期。我想使用“DateStart”、“DateEnd”和“Day”字段来创建一个新字段“Date”,它为“DateStart”和“DateEnd”内的每个“Day”分配一个特定日期间隔。

我已经使用 %--% 运算符将 DateStart 和 DateEnd 变成一个区间:

Week_Interval <- DateStart %--% DateEnd

但是我在弄清楚如何将 Day 字段与结果间隔内的日期匹配方面没有多大运气。我已经尝试通读 lubridate 文档,但其中似乎没有任何东西可以专门解决我的问题。我希望这里的人可能对此有一些经验,并可以帮助我指明正确的方向。

我的理想输出是这样的:

Week  DateStart    DateEnd      Day        Date
1     5-Aug-16     11-Aug-16    Monday     08-08-2016
2     12-Aug-16    18-Aug-16    Thursday   18-08-2016

日期遵循标准 dd-mm-yyyy 格式。

【问题讨论】:

  • 如果在 2 个开始日期和结束日期之间有 2 个星期一可以接受吗?
  • 理论上,在 2 个开始日期和结束日期之间不会有 2 个星期一,因为 DateStarts 都发生在星期五,而 DateEnds 都在星期四。是的,我会在编辑中展示我的理想输出。

标签: r lubridate


【解决方案1】:

DayDateStart 星期几之间的差取模7 并将其添加到DateStart

没有使用任何包。

dow <- c("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")
transform(DF, Date = 
  DateStart + (match(Day, dow) - 1 - as.POSIXlt(DateStart)$wday) %% 7)

给予:

  Week  DateStart    DateEnd      Day       Date
1    1 2016-08-05 2016-08-11   Monday 2016-08-08
2    2 2016-08-12 2016-08-18 Thursday 2016-08-18

注 1

如果您使用英语语言环境,alternative 写出星期几是:

dow <- weekdays(as.Date("1950-01-01") + 0:6)

注2

在示例中,两行的开始日期都是星期五。如果知道情况总是如此,我们可以通过将代码硬编码为 5 来缩短代码:

transform(DF, Date = DateStart + (match(Day, dow) - 1 - 5) %% 7)

注3

输入,以可重现的形式,是:

Lines <- "Week  DateStart    DateEnd      Day
1     5-Aug-16     11-Aug-16    Monday
2     12-Aug-16    18-Aug-16    Thursday"
DF <- read.table(text = Lines, header = TRUE)
fmt <- "%d-%b-%y"
DF <- transform(DF, DateStart = as.Date(DateStart, fmt),
  DateEnd = as.Date(DateEnd, fmt))

【讨论】:

    【解决方案2】:
    # example data
    df = read.table(text = "
    Week  DateStart    DateEnd      Day
    1     5-Aug-16     11-Aug-16    Monday
    2     12-Aug-16    18-Aug-16    Thursday
    ", header=T, stringsAsFactors=F)
    
    library(tidyverse)
    library(lubridate)
    
    df %>%
      group_by(Week, Day) %>%               # for each week and day
      mutate(Date = list(seq(dmy(DateStart), dmy(DateEnd), "1 day")),  # get sequence of dates between start and end
             Day2 = map(Date, weekdays)) %>%                           # get name of days for each date in the sequence
      unnest() %>%                          # unnest dates
      ungroup() %>%                         # forget the grouping
      filter(Day == Day2) %>%               # keep days that match
      select(-Day2)                         # remove unnecessary column
    
    # # A tibble: 2 x 5
    #    Week DateStart DateEnd   Day      Date      
    #   <int> <chr>     <chr>     <chr>    <date>    
    # 1     1 5-Aug-16  11-Aug-16 Monday   2016-08-08
    # 2     2 12-Aug-16 18-Aug-16 Thursday 2016-08-18
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-21
      • 2011-08-22
      • 2017-10-12
      • 2018-05-26
      • 1970-01-01
      • 1970-01-01
      • 2011-04-08
      • 2013-09-28
      相关资源
      最近更新 更多