#r #date
#r #Дата #lubridate
Вопрос:
Я использую lubridate и подумал, что это будет так просто
ymd("2010-01-31") months(0:23)
Но посмотрите, что получается. Все перепутано!
[1] "2010-01-31 UTC" "2010-03-03 UTC" "2010-03-31 UTC" "2010-05-01 UTC" "2010-05-31 UTC" "2010-07-01 UTC" "2010-07-31 UTC" "2010-08-31 UTC" "2010-10-01 UTC"
[10] "2010-10-31 UTC" "2010-12-01 UTC" "2010-12-31 UTC" "2011-01-31 UTC" "2011-03-03 UTC" "2011-03-31 UTC" "2011-05-01 UTC" "2011-05-31 UTC" "2011-07-01 UTC"
[19] "2011-07-31 UTC" "2011-08-31 UTC" "2011-10-01 UTC" "2011-10-31 UTC" "2011-12-01 UTC" "2011-12-31 UTC"
Затем я прочитал, как lubridate учитывает такие явления, как интервал, длительность и период. Итак, хорошо, я понимаю, что месяц — это фактически количество дней, определенное (365*4 1)/48 = 30.438 дней. Поэтому я попытался поумнеть и переписать ее как
ymd("2010-01-31") as.period(months(0:23))
Но это просто выдало ошибку.
Error in as.period.default(months(0:23)) :
(list) object cannot be coerced to type 'double'
Ответ №1:
Да, вы нашли правильный трюк: вернуться на день назад с первого числа следующего месяца.
Здесь в виде однострочной строки в базе R:
R> seq(as.Date("2010-02-01"), length=24, by="1 month") - 1
[1] "2010-01-31" "2010-02-28" "2010-03-31" "2010-04-30" "2010-05-31"
[6] "2010-06-30" "2010-07-31" "2010-08-31" "2010-09-30" "2010-10-31"
[11] "2010-11-30" "2010-12-31" "2011-01-31" "2011-02-28" "2011-03-31"
[16] "2011-04-30" "2011-05-31" "2011-06-30" "2011-07-31" "2011-08-31"
[21] "2011-09-30" "2011-10-31" "2011-11-30" "2011-12-31"
R>
Поэтому нет необходимости в lubridate, который (будучи прекрасным пакетом) не нужен для такой простой задачи, как эта. Кроме того, его перегрузка существующих базовых функций по-прежнему кажется мне несколько опасной…
Ответ №2:
Удивительно, как ввод вопроса фокусирует творческую энергию. Я думаю, что я разработал ответ. Я могу также опубликовать это здесь для следующей бедной души, которая считает, что тратит время впустую.
ymd("2010-02-01") months(0:23)-days(1)
Просто укажите первый день следующего месяца и сгенерируйте из него последовательность, но вычтите из нее 1 день, чтобы получить последний день предыдущего месяца.
[1] "2010-01-31 UTC" "2010-02-28 UTC" "2010-03-31 UTC" "2010-04-30 UTC" "2010-05-31 UTC" "2010-06-30 UTC" "2010-07-31 UTC" "2010-08-31 UTC" "2010-09-30 UTC"
[10] "2010-10-31 UTC" "2010-11-30 UTC" "2010-12-31 UTC" "2011-01-31 UTC" "2011-02-28 UTC" "2011-03-31 UTC" "2011-04-30 UTC" "2011-05-31 UTC" "2011-06-30 UTC"
[19] "2011-07-31 UTC" "2011-08-31 UTC" "2011-09-30 UTC" "2011-10-31 UTC" "2011-11-30 UTC" "2011-12-31 UTC"
Кстати, как мне избавиться от надоедливых обозначений «UTC». Часовые пояса спасают жизнь, когда они необходимы. В остальное время они доставляют неудобства.
Комментарии:
1. используется
strftime(date)
, чтобы избавиться от часового пояса. этоstrftime('2010-10-31 UTC')
дало бы вам2010-10-31
.2. @SachaEpskamp: Stackoverflow позволит мне принять мой ответ только через два дня. Я думаю, это довольно умно. Может быть другой обходной путь, который является более элегантным.
3. @Ramnath strftime дает мне дату предыдущего дня, потому что там, где я живу, полночь по Гринвичу фактически равна 19:00 предыдущего дня. Я нахожусь в восточном часовом поясе. strftime(ymd(«2010-02-01») месяцы(0:23)-дни(1)) [1] «2010-01-30 19:00:00» «2010-02-27 19:00:00» «2010-03-30 20:00:00» и т.д.