Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use strict behavior for aweek objects #21

Merged
merged 57 commits into from
Jun 6, 2019
Merged

Use strict behavior for aweek objects #21

merged 57 commits into from
Jun 6, 2019

Conversation

zkamvar
Copy link
Member

@zkamvar zkamvar commented May 21, 2019

This PR will fix #20 and fix #8

The aweek package is going through a bit of a change to make things more
consistent. The list of changes can be found in the NEWS.md. Please test out
this code and let me know if you encounter any problems. I plan to release
this the second week of June.

The breaking changes in this release are that it’s no longer possible to
combine aweek objects that have different week_start attributes and factors
no longer coerce factors (but will be converted to characters upon
combination.

In the previous release, I enabled global week_start parameters that allowed
the user to set the week_start variable globally.

Please test this out with:

# install.packages("remotes")
remotes::install_github("reconhub/aweek#21")

Below are some highlights:

You can now create aweek objects directly from data frames of week numbers!

library("aweek")
library("dplyr")
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
set_week_start("Sunday") # Set the global week_start (defaults to Monday)

You can use numeric week data to create weeks or dates with get_aweek()
and get_date(). By default, they will give you the first week of the
current year:

get_aweek()
#> <aweek start: Sunday>
#> [1] "2019-W01-1"
get_date()
#> [1] "2018-12-30"

They are vectorised so you can use a data frame with them:

# create a table with all days in the week
d    <- as.Date("2019-03-03") + 0:6
res  <- lapply(weekdays(d), function(i) date2week(d, week_start = i))
resn <- lapply(weekdays(d), function(i) date2week(d, week_start = i, numeric = TRUE))
datf <- data.frame(wday = rep(weekdays(d), each = 7), 
                   week = unlist(res), # note: unlist converts to character
                   week_number = unlist(resn),
                   year  = 2019,
                   stringsAsFactors = FALSE)
datf$day <- substring(datf$week, 10, 11)
datf <- as_tibble(datf)
datf
#> # A tibble: 49 x 5
#>    wday   week       week_number  year day  
#>    <chr>  <chr>            <dbl> <dbl> <chr>
#>  1 Sunday 2019-W10-1          10  2019 1    
#>  2 Sunday 2019-W10-2          10  2019 2    
#>  3 Sunday 2019-W10-3          10  2019 3    
#>  4 Sunday 2019-W10-4          10  2019 4    
#>  5 Sunday 2019-W10-5          10  2019 5    
#>  6 Sunday 2019-W10-6          10  2019 6    
#>  7 Sunday 2019-W10-7          10  2019 7    
#>  8 Monday 2019-W09-7           9  2019 7    
#>  9 Monday 2019-W10-1          10  2019 1    
#> 10 Monday 2019-W10-2          10  2019 2    
#> # … with 39 more rows

Here you can convert week definitions with different starts to the correct
dates (the week of 2019-03-03).

datf %>%
  mutate(aweek = get_aweek(week = week_number, 
                           year = year, 
                           day = day, 
                           start = wday)) %>%
  mutate(the_date = get_date(week = week_number, 
                             year = year, 
                             day = day, 
                             start = wday))
#> # A tibble: 49 x 7
#>    wday   week       week_number  year day   aweek      the_date  
#>    <chr>  <chr>            <dbl> <dbl> <chr> <aweek>    <date>    
#>  1 Sunday 2019-W10-1          10  2019 1     2019-W10-1 2019-03-03
#>  2 Sunday 2019-W10-2          10  2019 2     2019-W10-2 2019-03-04
#>  3 Sunday 2019-W10-3          10  2019 3     2019-W10-3 2019-03-05
#>  4 Sunday 2019-W10-4          10  2019 4     2019-W10-4 2019-03-06
#>  5 Sunday 2019-W10-5          10  2019 5     2019-W10-5 2019-03-07
#>  6 Sunday 2019-W10-6          10  2019 6     2019-W10-6 2019-03-08
#>  7 Sunday 2019-W10-7          10  2019 7     2019-W10-7 2019-03-09
#>  8 Monday 2019-W09-7           9  2019 7     2019-W10-1 2019-03-03
#>  9 Monday 2019-W10-1          10  2019 1     2019-W10-2 2019-03-04
#> 10 Monday 2019-W10-2          10  2019 2     2019-W10-3 2019-03-05
#> # … with 39 more rows

Or, if you have ISO week formatted strings (YYYY-Www-d), then you can use
as.aweek():

datf %>%
  mutate(aweek = as.aweek(week, start = wday)) %>%
  mutate(the_date = as.Date(aweek))
#> # A tibble: 49 x 7
#>    wday   week       week_number  year day   aweek      the_date  
#>    <chr>  <chr>            <dbl> <dbl> <chr> <aweek>    <date>    
#>  1 Sunday 2019-W10-1          10  2019 1     2019-W10-1 2019-03-03
#>  2 Sunday 2019-W10-2          10  2019 2     2019-W10-2 2019-03-04
#>  3 Sunday 2019-W10-3          10  2019 3     2019-W10-3 2019-03-05
#>  4 Sunday 2019-W10-4          10  2019 4     2019-W10-4 2019-03-06
#>  5 Sunday 2019-W10-5          10  2019 5     2019-W10-5 2019-03-07
#>  6 Sunday 2019-W10-6          10  2019 6     2019-W10-6 2019-03-08
#>  7 Sunday 2019-W10-7          10  2019 7     2019-W10-7 2019-03-09
#>  8 Monday 2019-W09-7           9  2019 7     2019-W10-1 2019-03-03
#>  9 Monday 2019-W10-1          10  2019 1     2019-W10-2 2019-03-04
#> 10 Monday 2019-W10-2          10  2019 2     2019-W10-3 2019-03-05
#> # … with 39 more rows

change_week_start() will allow you to re-calculate week numbers based on a
different week_start attribute

w <- as.aweek(datf$week, start = datf$wday)
head(w)
#> <aweek start: Sunday>
#> [1] "2019-W10-1" "2019-W10-2" "2019-W10-3" "2019-W10-4" "2019-W10-5"
#> [6] "2019-W10-6"
head(change_week_start(w, "Monday"))
#> <aweek start: Monday>
#> [1] "2019-W09-7" "2019-W10-1" "2019-W10-2" "2019-W10-3" "2019-W10-4"
#> [6] "2019-W10-5"

factor_aweek() will aggregate your weeks with levels that span the range.

factor_aweek(as.aweek(as.Date(c("2019-03-03", "2019-05-31"))))
#> <aweek start: Sunday>
#> [1] 2019-W10 2019-W22
#> 13 Levels: 2019-W10 2019-W11 2019-W12 2019-W13 2019-W14 ... 2019-W22

Created on 2019-05-30 by the reprex package (v0.3.0)

@zkamvar zkamvar self-assigned this May 21, 2019
zkamvar added 6 commits May 21, 2019 18:09
This addresses issues of missing week_starts
This now checks the English weekdays first and then tries the
current locale if those fail.
This mechanism is hopefully to avoid the same ambiguity problem
that I was trying to solve with c.aweek(). You can create aweek
objects from week numbers or characters, but the resulting aweek
object should not have a different week_start attribute based on
the first element in the vector.
@zkamvar
Copy link
Member Author

zkamvar commented May 31, 2019

@scottyaz, since you've used aweek in the past, would you mind testing out this version?

# install.packages("remotes")
remotes::install_github("reconhub/aweek#21")

@scottyaz
Copy link

scottyaz commented May 31, 2019 via email

@zkamvar
Copy link
Member Author

zkamvar commented May 31, 2019

Sure but it may be a few days.

Thank You!

@zkamvar zkamvar requested a review from dirkschumacher June 5, 2019 12:50
@dirkschumacher
Copy link
Member

dirkschumacher commented Jun 5, 2019

Just a quick note before I can look at it more in depth: I thought ISO weeks always start on Monday. Wouldn't a call to set_week_start invalidate all ISO weeks generated?

@zkamvar
Copy link
Member Author

zkamvar commented Jun 5, 2019

Just a quick note before I can look at it more in depth: I thought ISO weeks always start on Monday. Wouldn't a call to set_week_start invalidate all ISO weeks generated?

Yes, ISO weeks all start on Monday, but all aweek objects contain their own week_start attribute, which only changes if the user specifies, so using set_week_start() will not invalidate any previously created aweek objects.

@dirkschumacher
Copy link
Member

Installed and tested it. I don't have the time to go through the code really but it looks good to me and I really like the package.

@zkamvar zkamvar merged commit ce93c7d into master Jun 6, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Remove ambiguous behavior (breaking changes) Add data.frame.aweek method
3 participants