Извлечение предыдущего определенного дня на основе даты

#r

#r

Вопрос:

Существует ли конкретный способ извлечения определенного дня на основе пройденной даты. Пример, если пользователь передает Sys.Date() , пользователь должен получить предыдущую дату, которая была субботой. В случае, если сегодня суббота, пользователь должен получить саму сегодняшнюю дату, поскольку это суббота

 > Sys.Date()
[1] "2021-02-11"
 

Здесь мне нужна дата в предыдущую субботу этой даты (сегодня). ТАКИМ образом, ожидаемый результат ниже, чем в субботу

 [1] "2021-02-06" 
 

В случае, если

Ответ №1:

Вы можете использовать floor_date() from lubridate . Обратите внимание, что ваш день недели может быть региональным, поэтому 6 может быть или не быть субботой для всех (но вы можете установить week_start необязательный аргумент).

 library(lubridate)

x <- as.Date("2021-02-06")
floor_date(x, "week", 6)
# [1] "2021-02-06"

x <- Sys.Date()
floor_date(x, "week", 6)
# [1] "2021-02-06"
 

Ответ №2:

Следующее основано на формуле, приведенной в одной из виньеток пакета zoo, но не зависит от этого пакета или любого другого пакета.

Предположим, что x — это вектор Date класса, а d — день недели, где воскресенье = 0, понедельник = 1 и так далее. Затем

 X0 <- as.Date(d - 4, origin = "1970-01-01")
 

выпадает на день недели d, поэтому мы можем посчитать, сколько недель прошло с тех пор, включая любую долю недели, а затем округлить и умножить на 7, добавив это к X0, чтобы получить предыдущую дату, приходящуюся на день недели d (или x, если это уже тот день недели).

Таким образом, если элемент вектора класса даты x находится в день недели d, то следующий возвращает x для этого элемента, а в противном случае он дает предыдущую дату в этот день недели.

Что касается кода, если zoo загружен, то origin= аргумент может быть опущен.

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

 # x is Date vector, d is weekday where 0 = Sun, 1 = Mon, etc.
prev <- function(x, d = 0) 7 * floor(as.numeric(x - d   4) / 7)   
  as.Date(d - 4, origin = "1970-01-01")
 

Используя субботу, то есть день недели 6, в качестве примера,

 x <- as.Date("2000-01-08")   0:8
x
## [1] "2000-01-08" "2000-01-09" "2000-01-10" "2000-01-11" "2000-01-12"
## [6] "2000-01-13" "2000-01-14" "2000-01-15" "2000-01-16"

weekdays(x)
## [1] "Saturday"  "Sunday"    "Monday"    "Tuesday"   "Wednesday" "Thursday" 
## [7] "Friday"    "Saturday"  "Sunday"   

p <- prev(x, 6)  # 6 means Saturday
p
## [1] "2000-01-08" "2000-01-08" "2000-01-08" "2000-01-08" "2000-01-08"
## [6] "2000-01-08" "2000-01-08" "2000-01-15" "2000-01-15"

weekdays(p)
## [1] "Saturday" "Saturday" "Saturday" "Saturday" "Saturday" "Saturday" "Saturday"
## [8] "Saturday" "Saturday"
 

Ответ №3:

Вы можете попробовать:

 x <- as.Date("2021-02-11")
x - 8   which(format(seq(x - 7, by=1, length.out = 7), "%u") == 6)
#x - 8   which(format(seq(x - 7, by=1, length.out = 7), "%a") == "Sat") #Alternative depending on locale
#[1] "2021-02-06"
 

Или, если текущий день уже считается:

 x <- as.Date("2021-02-06")
x - 7   which(format(seq(x - 6, by=1, length.out = 7), "%u") == 6)
#[1] "2021-02-06"
 

Или, может быть:

 x <- seq(as.Date("2021-02-04"), by=1, length.out = 7)
x - rep(0:6, 2)[as.integer(format(x, "%u")) 2]
#[1] "2021-01-30" "2021-01-30" "2021-02-06" "2021-02-06" "2021-02-06"
#[6] "2021-02-06" "2021-02-06"
 

Или с помощью вектора поиска:

 x <- seq(as.Date("2021-02-04"), by=1, length.out = 7)
LU <- c(2:6, 0:1)
x - LU[as.integer(format(x, "%u"))]
#[1] "2021-01-30" "2021-01-30" "2021-02-06" "2021-02-06" "2021-02-06"
#[6] "2021-02-06" "2021-02-06"
 

Комментарии:

1. отлично. Но если дата есть "2021-02-06" , она отображается как "2021-01-30" . Но он все равно должен отображаться как "2021-02-06"

2. "2021-02-06" не предшествует "2021-02-06" . Но если вы хотите "2021-02-06" изменить значение 8 на a 7 и 9 на a 8 .

3. Спасибо, я попробовал x - 8 which(format(seq(x - 7, by=1, length.out = 6), "%u") == 6) . Но все равно получаю "2021-01-30"

4. О да, все еще один ко многим. Пожалуйста, смотрите Обновление.