Convert week number to date - r

I have a data frame in R with the week of the year that I would like to convert to a date. I know I have to pick a year and a day of the week so I am fixing those values at 2014 and 1. Converting this to a date seems simple:
as.Date(paste(2014,df$Week,1,sep=""),"%Y%U%u")
But this code only works if week is greater than 9. Week 1 - 9 returns NA. If I change the week to 01,02,03... it still returns NA.
Anyone see what I am missing?

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")

An alternative solution is to use date arithmetic from the lubridate package:
lubridate::ymd( "2014-01-01" ) + lubridate::weeks( df$Week - 1 )
The -1 is necessary because 2014-01-01 is already week 1. In other words, we want:
df$Week == 1 to map to 2014-01-01 (which is ymd("2014-01-01") + weeks(1-1))
df$Week == 2 to map to 2014-01-08 (which is ymd("2014-01-01") + weeks(2-1))
and so on.

Another option with lubridate
lubridate::parse_date_time(paste(2014, df$Week, 1, sep="/"),'Y/W/w')
W - week number, w - weekday number, 0-6 (Sun-Sat)

Another alternative is to make sure that week numbers have two digits, which can be done using stringr::str_pad(), which will add a pad="0" to make sure there are width=2 digits:
year <- 2015
week <- 1
as.Date(paste(year, week, "1", sep=""), "%Y%U%u")
#> [1] NA
as.Date(paste(year, stringr::str_pad(week,width=2, pad="0"), "1", sep=""), "%Y%U%u")
#> [1] "2015-01-05"
as.Date(paste(year, week, "1", sep="-"), "%Y-%U-%u")
#> [1] "2015-01-05"
Created on 2021-04-19 by the reprex package (v1.0.0)

It will be like using 2nd year = (week-52), 3rd year = (week -104)...so on
for(i in 1:456548)
{
if (train[i,2] > 0 & train[i,2] <53)
{
train["weekdate"] <- as.Date(paste(2016, train$week, 1, sep="-"), "%Y-%U-%u")
}
if (train[i,2] > 52 & train[i,2] <105)
{
train["weekdate"] <- as.Date(paste(2017, (train$week-52), 1, sep="-"), "%Y-%U-%u")
}
if (train[i,2] > 104 & train[i,2] <150)
{
train["weekdate"] <- as.Date(paste(2018, (train$week-104), 1, sep="-"), "%Y-%U-%u")
}
}

Related

Convert Year/Week to Timestamp (dd/mm/yyyy) [duplicate]

This question already has answers here:
Convert week number to date
(5 answers)
Closed 9 months ago.
I've got a Dataset that looks like this:
Year
Week
Cases
2010
1
2
2010
4
3
2010
5
5
2010
6
1
I would like to convert the Year-Week columns into a single timestamp column (dd/mm/yyyy). Day of the week could be the first or the last one.
Is there a simple way to solve this?
Best,
Daniel
The weeks function in lubridate and str_c function in stringr might provide it:
df <- tribble(~year, ~week, 2010,1,2010,4,2010,5,2010,6)
df_tbl <- df %>%
mutate(beg = ymd(str_c(year, "-01-01")),
date_var = beg + weeks(week))
df_tbl$date_var
If you count week 1 as starting on 1st January, you could do:
as.Date(paste(df$Year, 1, 1, sep = '-')) + 7 * (df$Week - 1)
#> [1] "2010-01-01" "2010-01-22" "2010-01-29" "2010-02-05"
If you count week 1 as starting on the first Monday of the year (as per ISO 8601) then you could use this little function:
year_week <- function(year, week) {
as.Date(unlist((Map(function(y, w) {
d <- which(lubridate::wday(as.Date(paste(y, 1, 1:7, sep = '-'))) == 2)
as.Date(paste(y, 1, d, sep = '-')) + (w - 1) * 7}, y = year, w = week))),
origin = '1970-01-01')
}
This will give you the date of the nth Monday in the year, so that we have:
year_week(df$Year, df$Week)
#> [1] "2010-01-04" "2010-01-25" "2010-02-01" "2010-02-08"

If date is on Sunday, then change date to the following Monday

Sunday date in mydates is 2018-05-06. I would like 1 day added so that 2018-05-06 becomes 2018-05-07 (Monday). That is, if a date falls on a Sunday add one day.
library(dplyr)
library(lubridate)
mydates <- as.Date(c('2018-05-01','2018-05-02','2018-05-05','2018-05-06'))
# find which are weekend dates
x = as.character(wday(mydates,TRUE))
if(x == 'Sun') { mydates + 1 }
# the Sunday date in mydates is 2018-05-06. I would like 1 day added so
that 2018-05-06 becomes 2018-05-07
Here's my error: Warning message:
In if (x == "Sun") { :
the condition has length > 1 and only the first element will be used
Try ifelse. Then convert to class Date.
as.Date(ifelse(x == 'Sun', mydates + 1, mydates), origin = '1970-01-01')
#[1] "2018-05-01" "2018-05-02" "2018-05-05" "2018-05-07"
X is a vector so you can use anif_else statement to increment the Sundays as follows:
library(dplyr)
library(lubridate)
new_dates <- if_else(x == 'Sun', mydates + days(1), mydates)
First, identify which of your dates are Sundays. Then, selectively add 1
library(lubridate)
mydates <- as.Date(c('2018-05-01','2018-05-02','2018-05-05','2018-05-06'))
i <- which(as.character(wday(mydates,TRUE))=="Sun")
mydates[i] <- mydates[i]+1
this outputs
"2018-05-01" "2018-05-02" "2018-05-05" "2018-05-07"
which, I believe, is the desired result.

R Week number from date starting on a Friday

I'd like to get week number in year which starts on Friday in R.
For example:
2016-01-01 to 2016-01-07 is 1st week of the year
2016-01-08 to 2016-01-14 is 2nd week of the year
Can you help?
One package you might find useful is Lubridate. It really helps with tasks using dates and times.
For example:
> library(lubridate)
> week(as.POSIXct("2016-01-01"))
[1] 1
Or, if you are curious about what week number Halloween falls on:
> week(as.Date("2016-10-31"))
[1] 44
for more info: https://cran.r-project.org/web/packages/lubridate/lubridate.pdf
You can use lubridate in this case, I've just had the same problem as you are. In my case I need it to be started on Wed, so this code below is to start week on Wednesday,
weekOnWed <- function(theDate) {
formattedDate <- dmy (theDate)
i <- 1
while (i <= 7) {
isWed <- dmy(paste("0", as.character(i), "/01/", year(formattedDate), sep = ""))
## because Wed is the 4th day of the week on Lubridate
you need to change the number below to 6 (as Fri is 6th day) on Lubridate
if (wday(isWed) == 4) {
break;
}
else {
i <- i + 1
}
}
firstWed <- day(isWed)
if (firstWed > 1) {
firstWeek <- 2
}
else {
firstWeek <- 1
}
rangeWeek <- as.integer(formattedDate - isWed) %/% 7
weekNum <- rangeWeek + firstWeek
weekNum
}
input: string (in dd-mm-yyyy) format
output of this function is week number in integer
hopefully that helps :)

R change integer to three integers

I have this number
20101213 which is a representation of this data 2010 Dec 13th I want to extract the year, month and day numbers from that number. So I should have three variables contain the values.
What I have tried:
value = 20101213
as.numeric(strsplit(as.character(value), "")[[1]])
The result is [1] 2 0 1 0 1 0 1 0
but I didn't know how to continue, may you help me please
You probably want to get this into a date-time format anyways for future computing, so how about:
(x <- strptime(20101213, "%Y%m%d"))
# [1] "2010-12-13 EST"
This will enable you to do computations that you wouldn't have been able to with just the year, month number, and day number, such as grabbing the day of the week (0=Sunday, 1=Monday, ...) or day of the year:
x$wday
# [1] 1
x$yday
# [1] 346
Further, you could easily extract the year, month number, and day of month number:
c(x$year+1900, x$mon+1, x$mday)
# [1] 2010 12 13
Edit: As pointed out by #thelatemail, an alternative that doesn't involve remembering offsets is:
as.numeric(c(format(x, "%Y"), format(x, "%m"), format(x, "%d")))
# [1] 2010 12 13
year <- as.numeric(substr(as.character(value),start = 1,stop = 4))
month <- as.numeric(substr(as.character(value),start = 5,stop = 6))
day <- as.numeric(substr(as.character(value),start = 7,stop = 8))
If you don't want to deal with string representation you could also just use mod function like this:
# using mod
year = floor(value/10000)
month = floor((value %% 10000)/100)
day = value %% 100
Which will then extract the relevant parts of the number as expected.

Format date strings comprising weeks and quarters as Date objects

I have dates in an R dataframe column formatted as character strings as WK01Q32014.
I want to turn each date into a Date() object.
So I altered the format to make it look like 01-3-2014. I want to try to do something like as.Date("01-3-2014","%W-%Q-%Y") for example, but there is no format code for quarters that I know of.
Is there any way to do this using the lubridate, zoo, or any other libraries?
I dont know of any specific function, but here's a basic one:
convert_WQ_to_Date <- function(D) {
weeks <- as.integer(substr(D, 3, 4))
quarter <- as.integer(substr(D, 6, 6))
year <- substr(D, 7, 10)
days <- 7 * ((quarter - 1) * 13 + (weeks-1))
as.Date(sprintf("%s-01-01", year)) + days
}
Example
D <- c("WK01Q32014", "WK01Q12014", "WK05Q42014", "WK01Q22014", "WK02Q32014")
convert_WQ_to_Date(D)
[1] "2014-07-02" "2014-01-01" "2014-10-29" "2014-04-02" "2014-07-09"
The week, quarter and year does not uniquely define a date so we will have to add some assumption. Here we add the assumption that the first week is the first day of the quarter, the second week is 7 days later and so on,
Below, we extract the qtr-year part and use as.yearqtr in the zoo package to convert that to a yearqtr object and then use as.Date to convert that to a date which is the first of the quarter. We then extract the week, subtract 1 and multiply by 7 to get the days offset. Adding the first of the quarter to the offset gives the result:
library(zoo)
xx <- "01-3-2014" # week-quarter-year
qtr.start <- as.Date(as.yearqtr(sub("...", "", xx), "%q-%Y"))
days <- 7 * (as.numeric(sub("-.*", "", xx)) - 1)
qtr.start + days
## [1] "2014-07-01"
Assuming the traditional notion of each quarter starting respectively at the 1st January, 1st April, 1st July and 1st September (in line with the quarters function), just start at these dates and add 7 days for each week:
x <- c("01-3-2014","01-1-2014","05-4-2014","01-2-2014","02-3-2014")
y <- as.numeric(substr(x,6,9))
m <- as.numeric(substr(x,4,4))
d <- as.numeric(substr(x,1,2))
as.Date(paste(y,(m-1)*3+1,"01",sep="-")) + (7*(d-1))
#[1] "2014-07-01" "2014-01-01" "2014-10-29" "2014-04-01" "2014-07-08"

Resources