Find out the number of days of a month in R
You can write simple function to do that:
numberOfDays <- function(date) {
m <- format(date, format="%m")
while (format(date, format="%m") == m) {
date <- date + 1
}
return(as.integer(format(date - 1, format="%d")))
}
Invoke as:
> date = as.Date("2011-02-23", "%Y-%m-%d")
> numberOfDays(date)
[1] 28
> date # date is unchanged
[1] "2011-02-23"
Counting number of days in months in r
library(dplyr)
df %>%
# distinct(date) %>% # unnecessary if no dupe dates
mutate(month = lubridate::floor_date(date, "month")) %>%
count(month)
Result
month n
1 2005-12-01 2
2 2006-01-01 3
3 2006-02-01 1
4 2007-03-01 3
5 2007-04-01 2
Data used:
df <- structure(list(date = structure(c(13145, 13148, 13149, 13150,
13151, 13183, 13574, 13575, 13578, 13613, 13614), class = "Date")), row.names = c(NA,
-11L), class = "data.frame")
Count the number of days in each month of a date range
Consider the functions f1, f2, f3
below
f1 <- function(d_first,d_last){
d_first <- as.Date(d_first)
d_last <- as.Date(d_last)
D <- seq(d_first, d_last, 1) # generate all days in [d_first,d_last]
M <- unique(format(D, "%m")) # all months in [d_first,d_lst]
f2 <- function(x) length(which(format(D, "%m") == x)) # returns number of days in month x
res <- vapply(M,f2,numeric(1))
return(cbind(unique(format(D, "%Y-%m")),res))
}
f3 <- function(k) f1(df$start[k],df$end[k])
output <- sapply(1:nrow(df), f3)
which yields
> output
[[1]]
res
01 "2014-01" "27"
02 "2014-02" "3"
[[2]]
res
02 "2014-02" "25"
03 "2014-03" "31"
04 "2014-04" "29"
[[3]]
res
02 "2014-02" "23"
03 "2014-03" "7"
From here on now, the rest is a matter of formatting. Indeed, a simple do.call(rbind, output)
will do the trick
> do.call(rbind, output)
res
01 "2014-01" "27"
02 "2014-02" "3"
02 "2014-02" "25"
03 "2014-03" "31"
04 "2014-04" "29"
02 "2014-02" "23"
03 "2014-03" "7"
Of the top of my head, to have the IDs you could set f4 <- function(k) cbind(df$id[k], f3(k))
and thus
> do.call(rbind, sapply(1:nrow(df), f4))
res
01 "1" "2014-01" "27"
02 "1" "2014-02" "3"
02 "1" "2014-02" "25"
03 "1" "2014-03" "31"
04 "1" "2014-04" "29"
02 "2" "2014-02" "23"
03 "2" "2014-03" "7"
But there probably are cleverer solutions.
Get the number of days from the date column
You need to first get the column MONTH
to Date
and then use any of the function shown here to get number of days in a month.
as.Date(paste0(1, df$MONTH), "%d%b,%Y")
#[1] "2017-01-01" "2017-02-01" "2017-03-01" "2017-04-01" "2017-05-01" "2017-06-01"
# "2017-07-01" "2017-08-01" "2017-09-01" "2017-10-01" "2017-11-01" "2017-12-01"
Hmisc::monthDays(as.Date(paste0(1, df$MONTH), "%d%b,%Y"))
#[1] 31 28 31 30 31 30 31 31 30 31 30 31
data
df <- structure(list(MONTH = structure(c(5L, 4L, 8L, 1L, 9L, 7L, 6L,
2L, 12L, 11L, 10L, 3L), .Label = c("Apr,2017", "Aug,2017", "Dec,2017",
"Feb,2017", "Jan,2017", "Jul,2017", "Jun,2017", "Mar,2017", "May,2017",
"Nov,2017", "Oct,2017", "Sep,2017"), class = "factor")), class =
"data.frame", row.names = c(NA, -12L))
R: number of days to month end using lubridate
In lubridate you can do:
days_in_month(now()) - mday(now())
Although that gives you a named vector, so it's better to do
as.numeric(days_in_month(now()) - mday(now()))
#> [1] 27
Thanks to @H1 for pointing out we can use now()
instead of month(now())
How to count the number of days, weeks, months in a date column of a dataframe in r?
Use format()
with the following codes:
date = strptime('2005-02-28', format='%Y-%m-%d')
format(date, '%j') # Decimal day of the year
format(date, '%U') # Decimal week of the year (starting on Sunday)
format(date, '%W') # Decimal week of the year (starting on Monday)
format(date, '%m') # Decimal month
Output:
[1] "059"
[1] "09"
[1] "09"
[1] "02"
Source
How to specify the number of days in each month for specific year using R?
You can get the last day of the month by moving back one day from the first of the next month. So, try this:
numDays <- function(month,year){
as.numeric(strftime(as.Date(paste(year+month%/%12,month%%12+1,"01",sep="-"))-1,"%d"))
}
Testing:
numDays(2,2012)
[1] 29
numDays(2,2011)
[1] 28
numDays(1,2011)
[1] 31
numDays(12,2011)
[1] 31
# vector of all month days in year 2000
sapply(1:12,numDays,2000)
[1] 31 29 31 30 31 30 31 31 30 31 30 31
Counts of numbers of date for service use in each month
Here's a {tidyverse} solution.
- Use
dplyr::summarize()
andseq()
to generate the full range of dates for each observation.- I include
end - 1
inseq()
to not include the end date in the count, consistent with your example.
- I include
- Convert these to months using
lubridate::floor_date(unit = "month")
(technically, changes each date to the first of the month). dplyr::count()
up month-days for eachid
.- Because you want columns for months with no observations in your output, I wrote a function to add unobserved months based on
tidyr::complete()
. - Finally,
tidyr::pivot_wider()
to get a column for each month.
library(tidyverse)
library(lubridate)
complete_months <- function(.data, month, ..., fill = list()) {
month <- pull(.data, {{ month }})
firstday <- floor_date(min(month, na.rm = TRUE), unit = "year")
lastday <- ceiling_date(max(month, na.rm = TRUE), unit = "year") - 1
allmonths <- seq(firstday, lastday, by = "month")
complete(.data, month = allmonths, ..., fill = fill)
}
month_counts <- df %>%
mutate(across(start:end, ymd)) %>%
group_by(id, obs = row_number()) %>%
summarize(
# use end - 1 in seq() to omit end date from count
month = floor_date(seq(start, end - 1, by = 1), unit = "month"),
.groups = "drop"
) %>%
count(month, id) %>%
complete_months(month, id, fill = list(n = 0)) %>%
mutate(month = strftime(month, "%Y_%b")) %>%
pivot_wider(
names_from = month,
values_from = n
)
month_counts
# # A tibble: 2 x 25
# id `2018_Jan` `2018_Feb` `2018_Mar` `2018_Apr` `2018_May` `2018_Jun`
# <chr> <int> <int> <int> <int> <int> <int>
# 1 A 0 0 0 30 31 30
# 2 B 0 0 0 0 0 0
# # ... with 18 more variables: `2018_Jul` <int>, `2018_Aug` <int>,
# # `2018_Sep` <int>, `2018_Oct` <int>, `2018_Nov` <int>, `2018_Dec` <int>,
# # `2019_Jan` <int>, `2019_Feb` <int>, `2019_Mar` <int>, `2019_Apr` <int>,
# # `2019_May` <int>, `2019_Jun` <int>, `2019_Jul` <int>, `2019_Aug` <int>,
# # `2019_Sep` <int>, `2019_Oct` <int>, `2019_Nov` <int>, `2019_Dec` <int>
Related Topics
Can the Value.Var in Dcast Be a List or Have Multiple Value Variables
Issue with Ggplot2, Geom_Bar, and Position="Dodge": Stacked Has Correct Y Values, Dodged Does Not
Buffer (Geo)Spatial Points in R with Gbuffer
Plot Background Colour in Gradient
Row-Wise Sort Then Concatenate Across Specific Columns of Data Frame
How to Perform Pairwise Operation Like '%In%' and Set Operations for a List of Vectors
How to Change Line Width in Ggplot
Converting Data Frame Column from Character to Numeric
Raw Text Strings for File Paths in R
Add Image in Title Page of Rmarkdown PDF
Make a Rectangular Legend, with Rows and Columns Labeled, in Grid
Pad with Leading Zeros to Common Width
How to Append a Whole Dataframe to a CSV in R