R: How to Judge Date in the Same Week

Identify dates in the same week

This will assign a unique integer to groups of dates that fall within a given week:

origin <- as.Date("2012-12-9")  ## A Sunday
weekID <- as.numeric(exampleDates - origin) %/% 7

data.frame(date = exampleDates,
weekday = weekdays(exampleDates),
week = weekID)
# date weekday week
# 1 2012-12-26 Wednesday 2
# 2 2012-12-27 Thursday 2
# 3 2012-12-28 Friday 2
# 4 2012-12-29 Saturday 2
# 5 2012-12-30 Sunday 3
# 6 2012-12-31 Monday 3
# 7 2013-01-01 Tuesday 3
# 8 2013-01-02 Wednesday 3
# 9 2013-01-03 Thursday 3
# 10 2013-01-04 Friday 3
# 11 2013-01-05 Saturday 3
# 12 2013-01-06 Sunday 4
# 13 2013-01-07 Monday 4
# 14 2013-01-08 Tuesday 4
# 15 2013-01-09 Wednesday 4

Find the day of a week

df = data.frame(date=c("2012-02-01", "2012-02-01", "2012-02-02")) 
df$day <- weekdays(as.Date(df$date))
df
## date day
## 1 2012-02-01 Wednesday
## 2 2012-02-01 Wednesday
## 3 2012-02-02 Thursday

Edit: Just to show another way...

The wday component of a POSIXlt object is the numeric weekday (0-6 starting on Sunday).

as.POSIXlt(df$date)$wday
## [1] 3 3 4

which you could use to subset a character vector of weekday names

c("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", 
"Friday", "Saturday")[as.POSIXlt(df$date)$wday + 1]
## [1] "Wednesday" "Wednesday" "Thursday"

Aggregate week and date in R by some specific rules

First we can convert the dates in df2 into year-month-date format, then join the two tables:

library(dplyr);library(lubridate)
df2$dt = ymd(df2$date)
df2$wk = day(df2$dt) %/% 7 + 1
df2$year_month_week = as.numeric(paste0(format(df2$dt, "%Y%m"), df2$wk))

df1 %>%
left_join(df2 %>% group_by(year_month_week) %>% slice(1) %>%
select(year_month_week, temperature))

Result

Joining, by = "year_month_week"
id year_month_week points temperature
1 1 2022051 65 36.1
2 1 2022052 58 36.6
3 1 2022053 47 NA
4 2 2022041 21 34.3
5 2 2022042 25 34.9
6 2 2022043 27 NA
7 2 2022044 43 NA

Convert week number to date

as.Date is calling the 1 to 9 as NA as it is expects two digits for the week number and can't properly parse it.

To fix it, add in some - to split things up:

as.Date(paste(2014, df$Week, 1, sep="-"), "%Y-%U-%u")

Generate dates based on a date column -same day of week, same month

We can convert the 'indexdt' to Date class, loop over the elements, get a sequence of dates with the end specified as the end of the month with ceiling_date (from lubridate) and specify by as "week" in a list and then unnest the list column

library(dplyr)
library(purrr)
library(lubridate)
library(tidyr)
df1 %>%
mutate(indexdt = as.Date(indexdt, "%m-%d-%Y"),
date = map(indexdt, ~ seq(.x, ceiling_date(.x, 'month'),
by = 'week')[-1])) %>%
unnest(c(date))

Or using data.table

library(data.table)    
setDT(df1)[, indexdt := as.Date(indexdt, "%m-%d-%Y")]
df1[, .(date = seq(indexdt, ceiling_date(indexdt, "month"),
by = "week")[-1]), .(indexdt)]

For 2020, add one year

df1 %>%
mutate(indexdt = as.Date(indexdt, "%m-%d-%Y"),
date = map(indexdt, ~ seq(.x + years(1),
ceiling_date(.x + years(1), 'month'), by = 'week')[-1])) %>%
unnest(c(date))

with data.table

df1[, .(date = seq(indexdt, ceiling_date(indexdt +years(1), "month"), 
by = "week")[-1]), .(indexdt)]

data

df1 <- structure(list(indexdt = c("01-02-2019", "08-15-2019")), class = "data.frame", row.names = c(NA, 
-2L))

R: Round down dates to first day of the week

cut() from base R has two methods for objects of class Date and POSIXt which assume that weeks start on Monday by default (but may be changed to Sunday using start.on.monday = FALSE).

dates <- c("2016-04-04", "2016-04-05", "2016-04-06", "2016-04-07", "2016-04-08", 
"2016-04-09", "2016-04-10", "2016-04-11", "2016-04-12", "2016-04-13",
"2016-04-14")
result <- data.frame(
dates,
cut_Date = cut(as.Date(dates), "week"),
cut_POSIXt = cut(as.POSIXct(dates), "week"),
stringsAsFactors = FALSE)

result
# dates cut_Date cut_POSIXt
#1 2016-04-04 2016-04-04 2016-04-04
#2 2016-04-05 2016-04-04 2016-04-04
#3 2016-04-06 2016-04-04 2016-04-04
#4 2016-04-07 2016-04-04 2016-04-04
#5 2016-04-08 2016-04-04 2016-04-04
#6 2016-04-09 2016-04-04 2016-04-04
#7 2016-04-10 2016-04-04 2016-04-04
#8 2016-04-11 2016-04-11 2016-04-11
#9 2016-04-12 2016-04-11 2016-04-11
#10 2016-04-13 2016-04-11 2016-04-11
#11 2016-04-14 2016-04-11 2016-04-11

Note that cut() returns factors which is perfect for aggregation as requested by the OP:

str(result)
#'data.frame': 11 obs. of 3 variables:
# $ dates : chr "2016-04-04" "2016-04-05" "2016-04-06" "2016-04-07" ...
# $ cut_Date : Factor w/ 2 levels "2016-04-04","2016-04-11": 1 1 1 1 1 1 1 2 2 2 ...
# $ cut_POSIXt: Factor w/ 2 levels "2016-04-04","2016-04-11": 1 1 1 1 1 1 1 2 2 2 ...

However, for plotting aggregated values with ggplot2 (and if there is a large number of weeks which might clutter the axis) it might be better to switch from a discrete time scale to a continuous time scale. Then it is necessary to coerce factors back to Date or POSIXct:

as.Date(as.character(result$cut_Date))
as.POSIXct(as.character(result$cut_Date))

Get the difference between dates in terms of weeks, months, quarters, and years

what about this:

# get difference between dates `"01.12.2013"` and `"31.12.2013"`

# weeks
difftime(strptime("26.03.2014", format = "%d.%m.%Y"),
strptime("14.01.2013", format = "%d.%m.%Y"),units="weeks")
Time difference of 62.28571 weeks

# months
(as.yearmon(strptime("26.03.2014", format = "%d.%m.%Y"))-
as.yearmon(strptime("14.01.2013", format = "%d.%m.%Y")))*12
[1] 14

# quarters
(as.yearqtr(strptime("26.03.2014", format = "%d.%m.%Y"))-
as.yearqtr(strptime("14.01.2013", format = "%d.%m.%Y")))*4
[1] 4

# years
year(strptime("26.03.2014", format = "%d.%m.%Y"))-
year(strptime("14.01.2013", format = "%d.%m.%Y"))
[1] 1

as.yearmon() and as.yearqtr() are in package zoo. year() is in package lubridate.
What do you think?

How to get week starting date from a date in R

Use the floor_date function from the lubridate package.

library("lubridate")
floor_date(as.Date("04/20/2017", "%m/%d/%Y"), unit="week")


Related Topics



Leave a reply



Submit