Как преобразовать дату в ближайшие выходные (суббота)

У меня есть фрейм данных с датой в формате «% d-% m-% Y» и номер недели. Даты - будние дни, и я хочу, чтобы суббота этой недели была в другом столбце.

Сначала я проверял, является ли дата будним или выходным днем, используя функцию в пакете Chron, но это была логическая проверка. Я отформатировал переменную даты в формате даты и извлек номер недели для каждой даты.

df = data.frame(date=c("2014-08-20", "2014-08-25", "2014-10-08")) 
df$date=as.Date(df$date,format="%Y-%m-%d")
df$week=week(ymd(df$date))

Ожидаемый результат должен быть:

date        week    EOW  
2014-08-20   34   2014-08-23

2014-08-25   34   2014-08-30

2014-10-08   41   2014-10-11

person Ami    schedule 30.01.2019    source источник


Ответы (3)


Базовый вариант R. Сначала создайте список всех дней, затем match его с weekdays и вычтите его из 6 (так как мы хотим субботу), чтобы получить, сколько дней нам нужно добавить в исходный столбец date.

all_days <- c("Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday")

#As @nicola mentioned this is locale dependent
#If your locale is not English you need weekdays in your current locale
#which you can manually write as shown above or do any one of the following

#all_days <- weekdays(seq(as.Date("2019-01-14"),by="day",length.out=7))
#OR
#all_days <- format(seq(as.Date("2019-01-14"),by="day",length.out=7), "%A")

df$EOW <- df$date + 6 - match(weekdays(df$date), all_days)

df
#        date week        EOW
#1 2014-08-20   34 2014-08-23
#2 2014-08-25   34 2014-08-30
#3 2014-10-08   41 2014-10-11

Или lubridate имеет функцию ceiling_date, которая при использовании с unit = "week" вернет вам следующее «воскресенье», поэтому мы вычитаем из него 1 день, чтобы вместо этого получить «субботу».

library(lubridate)
df$EOW <- ceiling_date(df$date, unit = "week") - 1
person Ronak Shah    schedule 30.01.2019

Другой способ использования

library(data.table)
df <- data.table(date=c("2014-08-20", "2014-08-25", "2014-10-08")) 
df$date=as.Date(df$date,format="%Y-%m-%d")
df$week=week(ymd(df$date))

## if the locale is not English, please use the local values for days 
days <- data.frame(DOW = c("Monday", "Tuesday", "Wednesday", "Thursday","Friday", "Saturday", "Sunday"))
days$day <- seq(1,7,1)

df <- df[,DOW:= weekdays(date)]
df <- merge(df, days, all.x = T, by = "DOW")

df <- df[, EOW := date + (6 - day)]
df

         DOW       date week day        EOW
1:    Monday 2014-08-25   34   1 2014-08-30
2: Wednesday 2014-08-20   34   3 2014-08-23
3: Wednesday 2014-10-08   41   3 2014-10-11
person Hardik Gupta    schedule 30.01.2019
comment
Что касается другого ответа, это решение зависит от локали. Смотрите мой комментарий там. - person nicola; 30.01.2019

Играем с синтаксисом data.table join:

library(data.table)

# Create a saturdays dataset
saturdays2014 <- data.table(date = seq(as.Date("2014-01-01"), as.Date("2014-12-31"), by = 1))
Sys.setlocale("LC_ALL","English")
saturdays2014 <- saturdays2014[weekdays(date) == "Saturday"]

# convert df to data.table and date to a Date variable
setDT(df)[, date := as.Date(date)]

# Join
df[saturdays2014, on = "date", roll = 6, EOW := i.date]
df    
#          date        EOW
# 1: 2014-08-20 2014-08-23
# 2: 2014-08-25 2014-08-30
# 3: 2014-10-08 2014-10-11
person sindri_baldur    schedule 30.01.2019
comment
Также местный депендент, но его должно быть достаточно для фильтрации, чтобы знать одну дату, которая является субботой, и оттуда использовать тот факт, что они происходят каждые 7 дней. - person sindri_baldur; 30.01.2019