Generate a sequence of the last day of the month over two years
Yes, you found the correct trick: going back a day from the first of the next month.
Here is as a one-liner in base 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>
So no need for lubridate which (while being a fine package) isn't needed for simple task like this. Plus, its overloading of existing base functions still strikes me as somewhat dangerous...
generate a date sequence of last day of month in R
This gives a sequence of end-of-month dates from the year/month of st
to the year/month of en
.
library(zoo)
as.Date(seq(as.yearmon(st), as.yearmon(en), by = 1 / freq), frac = 1)
In the above st
and en
could be any class that converts to yearmon
including yearmon
itself, Date
, character strings or numeric. For example, "2000-02-01"
, "2000-02"
, as.Date("2000-02-01")
, 2000+1/12
.
If en
is a date and the end date of the sequence should be no later than en
then replace as.yearmon(en)
with the following which subtracts 1/12 if en
is not at the end of the month.
as.yearmon(en) - (as.Date(en) < as.Date(as.yearmon(en), frac = 1)) / 12
Similarly if st
is a date and the starting date of the sequence should be no later than st
use the same idea to subtract 1/12 if st
is not at the end of the month replacing as.yearmon(st)
with
as.yearmon(st) - (as.Date(st) < as.Date(as.yearmon(st), frac = 1)) / 12
There is some question regarding whether we really need dates at all since they are always at the end of the month. It seems that the point is to create a year/month sequence and the end-of-month dates are just a way to represent that.
A simpler way would be this yearmon
sequence directly.
seq(as.yearmon(st), as.yearmon(en), by = 1 / freq)
find last day of month in a sequence of dates
Try:
which(ave(as.numeric(ds),format(ds,"%Y%m"),FUN=function(x) x==max(x))==1)
Generate date sequence by months
I think this is most elegantly solved by taking the day of the month component out of the equation while you are generating the sequence. With the clock package, you can generate a month precision sequence, then easily set the day to the last day of the month.
library(clock)
start <- as.Date("2014-03-31")
end <- as.Date("2021-09-30")
start <- calendar_narrow(as_year_month_day(start), "month")
end <- calendar_narrow(as_year_month_day(end), "month")
# Month precision dates
start
#> <year_month_day<month>[1]>
#> [1] "2014-03"
end
#> <year_month_day<month>[1]>
#> [1] "2021-09"
seq(start, end, by = 3) |>
set_day("last") |>
as.Date()
#> [1] "2014-03-31" "2014-06-30" "2014-09-30" "2014-12-31" "2015-03-31"
#> [6] "2015-06-30" "2015-09-30" "2015-12-31" "2016-03-31" "2016-06-30"
#> [11] "2016-09-30" "2016-12-31" "2017-03-31" "2017-06-30" "2017-09-30"
#> [16] "2017-12-31" "2018-03-31" "2018-06-30" "2018-09-30" "2018-12-31"
#> [21] "2019-03-31" "2019-06-30" "2019-09-30" "2019-12-31" "2020-03-31"
#> [26] "2020-06-30" "2020-09-30" "2020-12-31" "2021-03-31" "2021-06-30"
#> [31] "2021-09-30"
Created on 2022-08-15 by the reprex package (v2.0.1)
Create sequence of date on every last day of month
If you want last day of month, instead of start from 2018-01-31
, try
seq(as.Date("2018-02-01",format="%Y-%m-%d"),by="month",length.out=6) -1
[1] "2018-01-31" "2018-02-28" "2018-03-31" "2018-04-30" "2018-05-31" "2018-06-30"
Sequence of dates by each next 15th or last day of month
start <- as.Date("2014-05-03")
end <- as.Date("2014-07-01")
library(lubridate)
floor_date(seq(start, end, by = 'month'), unit = "month") + 14
ceiling_date(seq(start, end, by = 'month'), unit = "month")-1
Sequence by the month and use floor_date
from the lubridate
package to start at the beginning of the month.
create sequence of months and days with no year
We can create a date sequence (any year would work, no need to be 2001 in my example), and then use the format
function.
format(seq.Date(as.Date("2001-10-31"), as.Date("2001-12-31"), by = 1),
format = "%m-%d")
# [1] "10-31" "11-01" "11-02" "11-03" "11-04" "11-05" "11-06" "11-07" "11-08" "11-09" "11-10"
# [12] "11-11" "11-12" "11-13" "11-14" "11-15" "11-16" "11-17" "11-18" "11-19" "11-20" "11-21"
# [23] "11-22" "11-23" "11-24" "11-25" "11-26" "11-27" "11-28" "11-29" "11-30" "12-01" "12-02"
# [34] "12-03" "12-04" "12-05" "12-06" "12-07" "12-08" "12-09" "12-10" "12-11" "12-12" "12-13"
# [45] "12-14" "12-15" "12-16" "12-17" "12-18" "12-19" "12-20" "12-21" "12-22" "12-23" "12-24"
# [56] "12-25" "12-26" "12-27" "12-28" "12-29" "12-30" "12-31"
sequence of monthly dates making sure it's the same day, or the last day of month in case of invalid
The simplest solution is %m+% from lubridate, which solves this exact problem. So:
seq_monthly <- function(from,length.out) {
return(from %m+% months(c(0:(length.out-1))))
}
Output:
> seq_monthly(as.Date("2015-01-31"),length.out=4)
[1] "2015-01-31" "2015-02-28" "2015-03-31" "2015-04-30"
Create end of the month date from a date variable
To get the end of months you could just create a Date
vector containing the 1st of all the subsequent months and subtract 1 day.
date.end.month <- seq(as.Date("2012-02-01"),length=4,by="months")-1
date.end.month
[1] "2012-01-31" "2012-02-29" "2012-03-31" "2012-04-30"
Related Topics
Table of Interactions - Case With Pets and Houses
Tools For Making Latex Tables in R
Convert the Values in a Column into Row Names in an Existing Data Frame
Read All Worksheets in an Excel Workbook into an R List With Data.Frames
Save Multiple Ggplots Using a For Loop
Manually Setting Group Colors For Ggplot2
Combine Multiple Columns into Tidy Data
How to Use Facets With a Dual Y-Axis Ggplot
Chopping a String into a Vector of Fixed Width Character Elements
Lapply VS For Loop - Performance R
Reasons For Using the Set.Seed Function
Limit Ggplot2 Axes Without Removing Data (Outside Limits): Zoom
How to Delete Multiple Values from a Vector
Increase Distance Between Text and Title on the Y-Axis
Adding a New Column to Each Element in a List of Tables or Data Frames