Учитывая начальную дату, я хочу сгенерировать последовательность дат с ежемесячными интервалами, гарантируя, что каждый элемент имеет тот же день, что и первоначальная дата или последний день месяца, если тот же день приведет к недействительной дате.Последовательность месячных дат, удостоверяющая, что это тот же день или последний день месяца в случае недействительности
Звучит довольно стандартно, правда?
Использование difftime
невозможно. Вот что говорит файл справки из difftime
:
Единицы, такие как «месяцев» не представляется возможным, поскольку они не имеют постоянной длины. Чтобы создать интервалы месяцев, кварталов или лет, используйте seq.Date или seq.POSIXt.
Но глядя на файле справки seq.POSIXt
Я считаю, что:
Использование «месяц» первые успехи в месяц, не меняя день: если это приводит к недопустимого день месяца, он пересчитывается в в следующий месяц: см. примеры.
Это пример в файле справки.
seq(ISOdate(2000,1,31), by = "month", length.out = 4)
> seq(ISOdate(2000,1,31), by = "month", length.out = 4)
[1] "2000-01-31 12:00:00 GMT" "2000-03-02 12:00:00 GMT"
"2000-03-31 12:00:00 GMT" "2000-05-01 12:00:00 GMT"
Таким образом, учитывая, что начальная дата на 31 день, это даст некорректные даты в феврале, апреле и т.д. Таким образом, последовательность в конечном итоге на самом деле пропуск этих месяцев, потому что он «рассчитывает вперед» и в конечном итоге с марта-02, а не с 29 февраля.
Если я начну на 2000-01-31, я хотел бы последовательность следующим образом:
- 2000-01-31
- 2000-02-
- 2000-03- 31
- 2000-04-30
- ...
И он с hould правильно обрабатывать високосных лет, так что, если начальная дата 2015-01-31 последовательность должна быть:
- 2015-01-31
- 2015-02-
- 2015-03 -31
- 2015-04-30
- ...
это только примеры, иллюстрирующие проблему, и я не знаю начальную дату заранее, нет Я могу предположить что-нибудь об этом. Первоначальная дата может быть в середине месяца (2015-01-15), и в этом случае seq
отлично работает. Но это также может быть, как и в примерах, ближе к концу месяца по датам, поскольку использование только seq
было бы проблематичным (дни 29, 30 и 31). Я не могу предположить, что начальная дата - последний день месяца.
Я осмотрелся, пытаясь найти решение. В некоторых вопросах здесь, в SO (например, здесь) есть «трюк», чтобы получить последний день месяца, получив первый день следующего месяца и просто вычтите 1. И найти первый день «легко», потому что он только день 1.
так что мое решение до сих пор:
# Given an initial date for my sequence
initial_date <- as.Date("2015-01-31")
# Find the first day of the month
library(magrittr) # to use pipes and make the code more readable
firs_day_of_month <- initial_date %>%
format("%Y-%m") %>%
paste0("-01") %>%
as.Date()
# Generate a sequence from initial date, using seq
# This is the sequence that will have incorrect values in months that would
# have invalid dates
given_dat_seq <- seq(initial_date, by = "month", length.out = 4)
# And then generate an auxiliary sequence for the last day of the month
# I do this generating a sequence that starts the first day of the
# same month as initial date and it goes one month further
# (lenght 5 instead of 4) and substract 1 to all the elements
last_day_seq <- seq(firs_day_of_month, by = "month", length.out = 5)-1
# And finally, for each pair of elements, I take the min date of both
pmin(given_dat_seq, last_day_seq[2:5])
он работает, но, в то же время, своего рода немой, Hacky и запутанные. Поэтому мне это не нравится. И самое главное, я не могу поверить, что в этом нет более простого способа сделать это.
Может ли кто-нибудь указать мне на более простое решение? (Думаю, это должно быть так просто, как seq(initial_date, "month", 4)
, но, видимо, это не так). Я искал его и смотрел здесь в списках рассылки SO и R, но помимо трюков, о которых я говорил выше, я не мог найти решение.
не удалось вы просто делаете 'seq (as.Date (" 2015-01-31 ") + 1, length = 4, by =" month ") - 1'? – mtoto
Нет, потому что начальная дата произвольная (в этом конкретном примере я использовал январь-31, чтобы проиллюстрировать проблему, но я не знаю начальную дату заранее, и это не всегда последний день месяца). Если я сделаю так, как вы говорите, и исходная дата будет «2015-01-15», моя последовательность будет всегда на 16-й день, когда она должна быть на 15-й день каждый месяц. Спасибо, ты заставил меня понять, что не было ясно в моем довольно длинном вопросе. Я отредактирую его. – elikesprogramming