Манипуляции с датами с использованием as.POSIXlt
Вопрос
Я пытаюсь найти ближайшее к сегодняшнему воскресенью.
Я определяю сегодняшний день как:
dt <- as.Date("2014-06-04")
Я могу найти последнее воскресенье следующим образом:
dt - as.POSIXlt(dt)$wday
[1] "2014-06-01"
Я могу найти следующее воскресенье следующим образом:
dt + as.POSIXlt(dt)$wday
[1] "2014-06-07"
Не знаю, почему следующее не работает:
ifelse(as.POSIXlt(dt)$wday <= 3,
dt - as.POSIXlt(dt)$wday,
dt + as.POSIXlt(dt)$wday)
[1] 16222
Я получаю номер: 16222
вместо свидания.
Каждое из следующих утверждений работает ожидаемым образом:
as.POSIXlt(dt)$wday
class(as.POSIXlt(dt)$wday)
as.POSIXlt(dt)$wday <= 3
Есть идеи??
Решение
Кажется, что ifelse
возвращает вектор и удаляет класс «POSIX» из ваших дат.Почему бы не сделать
dt + ifelse(as.POSIXlt(dt)$wday <= 3, -1, 1) * as.POSIXlt(dt)$wday
вместо.
Другие советы
Другое решение:восстановите атрибут класса, вызвав, например:
structure(ifelse(as.POSIXlt(dt)$wday <= 3,
dt - as.POSIXlt(dt)$wday,
dt + as.POSIXlt(dt)$wday), class="Date")
Нет необходимости использовать ifelse
вот, классика if/else
выполню работу:
if(as.POSIXlt(dt)$wday <= 3) dt - as.POSIXlt(dt)$wday else dt + as.POSIXlt(dt)$wday
[1] "2014-06-01"
Или еще проще:
wday <- as.POSIXlt(dt)$wday
dt + if(wday<= 3) -wday else wday
1) Попробуй это:
wday <- as.POSIXlt(dt)$wday
dt + ifelse(wday <= 3, -wday, 7-wday)
Это касается ifelse
к количеству добавленных или вычтенных дней. ifelse
хорошо работает с простыми числами, но не со сложными типами, такими как "Date"
class, поэтому это позволяет избежать применения ifelse
к "Date"
объекты класса.
Обратите внимание, что если wday > 3
тогда мы хотим добавить 7-wday
и не wday
(как в вопросе).
Решение здесь продолжает работать, даже если dt
представляет собой вектор дат.
2) Обратите внимание, что вторую строку ответа в (1) можно альтернативно записать следующим образом, при котором сначала вычисляется последнее воскресенье (dt-wday
) и добавляет 7, чтобы получить следующее воскресенье, если это прошлая среда недели.
dt - wday + ifelse(wday > 3, 7, 0)
3) Еще один способ выразить это:
dt - wday + 7 * (wday > 3)