Find most recent Monday for a dataframe

前端 未结 6 591
甜味超标
甜味超标 2021-01-15 02:35

I have a dataframe object, and among the fields in it, I have a dates:

df$dates

I need to add a column which is \'Week Starting\', i.e.

相关标签:
6条回答
  • 2021-01-15 02:53

    A simple base-R way if your dates are properly coded as date class in R: as.Date(unclass(dates)-unclass(dates)%%7-3). You unclass it do get number of days since 1970-01-01. Then subtract remainder from division on 7 (day of the week!). Then subtract 3 because 1970-01-01 was Thursday –

    Also you can group your data by week, and then create a column of "minimal date of that week". Here is how to do it in data.table package:

    df=data.table(df)
    df[,lastMonday:=min(dates),by=.(week(dates))]
    

    It should work if you dont have spaces in dates. Also, in some locales week starts with sunday, so you should be careful. And you will need additional grouping variable, if your dates span for more than a year

    0 讨论(0)
  • 2021-01-15 02:55

    How about just subtracting from the dates the number of days required to get to the previous Monday? e.g if your data is

    dates <- as.Date(c("2000-07-12", "2005-02-19", "2010-09-01"))
    weekdays(dates)
    # [1] "Wednesday" "Saturday"  "Wednesday"
    

    then you can compare this to a vector

    wdays <- setNames(0:6, c("Monday", "Tuesday", "Wednesday",
                "Thursday", "Friday", "Saturday", "Sunday"))
    

    and subtract the required number of days from each date, ie

    dates - wdays[weekdays(dates)]
    #   Wednesday     Saturday    Wednesday 
    #"2000-07-10" "2005-02-14" "2010-08-30" 
    

    will give the dates of the Monday preceding each date in dates. To test:

    weekdays(dates - wdays[weekdays(dates)])
    #Wednesday  Saturday Wednesday 
    # "Monday"  "Monday"  "Monday" 
    

    Everything can be written also in one line as

    dates - match(weekdays(dates), c("Monday", "Tuesday", "Wednesday", 
       "Thursday", "Friday", "Saturday", "Sunday")) + 1
    #"2000-07-10" "2005-02-14" "2010-08-30" 
    
    0 讨论(0)
  • 2021-01-15 03:04

    Simples:

    dates <-(Sys.Date()+1:30)
    week.starts <- as.Date(sapply (dates, function(d) { return (d + (-6 - as.POSIXlt(d)$wday %% -7 ))}), origin = "1970-01-01")
    

    and running as

    d <- data.frame(dataes=dates, monday=week.starts)
    

    gives

           dataes     monday
    1  2015-09-25 2015-09-21
    2  2015-09-26 2015-09-21
    3  2015-09-27 2015-09-21
    4  2015-09-28 2015-09-28
    5  2015-09-29 2015-09-28
    6  2015-09-30 2015-09-28
    7  2015-10-01 2015-09-28
    8  2015-10-02 2015-09-28
    9  2015-10-03 2015-09-28
    10 2015-10-04 2015-09-28
    11 2015-10-05 2015-10-05
    12 2015-10-06 2015-10-05
    13 2015-10-07 2015-10-05
    14 2015-10-08 2015-10-05
    15 2015-10-09 2015-10-05
    16 2015-10-10 2015-10-05
    17 2015-10-11 2015-10-05
    18 2015-10-12 2015-10-12
    19 2015-10-13 2015-10-12
    20 2015-10-14 2015-10-12
    21 2015-10-15 2015-10-12
    22 2015-10-16 2015-10-12
    23 2015-10-17 2015-10-12
    24 2015-10-18 2015-10-12
    25 2015-10-19 2015-10-19
    26 2015-10-20 2015-10-19
    27 2015-10-21 2015-10-19
    28 2015-10-22 2015-10-19
    29 2015-10-23 2015-10-19
    30 2015-10-24 2015-10-19
    

    Similar approach, example:

    # data
    d <- data.frame(date = as.Date( c("20/09/2015","24/09/2015","28/09/2015","01/10/2015"), "%d/%m/%Y"))
    
    # get monday
    d$WeekStart <- d$date - 6 - (as.POSIXlt(d$date)$wday %% -7)
    
    d
    # result
    #         date  WeekStart
    # 1 2015-09-20 2015-09-14
    # 2 2015-09-24 2015-09-21
    # 3 2015-09-28 2015-09-28
    # 4 2015-10-01 2015-09-28
    
    0 讨论(0)
  • 2021-01-15 03:04
    a[1] <-as.Date("2016-08-20")
    

    Finding Next day (Here "Monday")

    a[1] + match("Monday",weekdays(seq(a[1]+1, a[1]+6,"days")))
    

    "2016-08-22"

    Finding Last Day (Here "Friday")

    a[1] + (match("Friday",weekdays(seq(a[1]+1, a[1]+6,"days")))-7)
    

    "2016-08-19"

    0 讨论(0)
  • 2021-01-15 03:10

    A base R approach with the function strftime.

    df$Week.Start <- dates-abs(1-as.numeric(strftime(df$dates, "%u")))
    

    This can be a one-liner but we'll create a few variables to see what's happening. The %u format pattern for dates returns the day of the week as a single decimal number. We can convert that number to numeric and subtract the distance from our dates. We can then subtract that vector from our date column.

    day_of_week <- as.numeric(strftime(df$dates, "%u"))
    day_diff <- abs(1-day_of_week)
    df$Week.Start <- dates-day_diff
    #        dates Week.Start
    # 1 2042-10-22 2042-10-20
    # 2 2026-08-14 2026-08-10
    # 3 2018-11-23 2018-11-19
    # 4 2017-08-21 2017-08-21
    # 5 2022-05-26 2022-05-23
    # 6 2037-05-27 2037-05-25
    

    Data

    set.seed(7)
    all_dates <- seq(Sys.Date(), Sys.Date()+10000, by="days")
    dates <- sample(all_dates, 20)
    df <- data.frame(dates)
    
    0 讨论(0)
  • 2021-01-15 03:13

    If you want nearest any day and hour to the current date, use this function:

    dayhour <- function(day,hour){
       k <- as.Date(Sys.time())+day-as.numeric(format(strptime(Sys.time(),format="%Y-%m-%d %H:%M:%S"), format ='%u'))
       dh <- format(strptime(paste(k,hour), format="%Y-%m-%d %H"), format="%A %H")
       return(dh)
    }
    

    For the weekdays use 0 to 6 as day argument for sunday to saturday respectively:

    > dayhour(0,17)
    [1] "Sunday 17"
    
    0 讨论(0)
提交回复
热议问题