diff --git a/DESCRIPTION b/DESCRIPTION index 11220a6..b869148 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -19,6 +19,7 @@ Imports: lubridate, magrittr, purrr, + rlang, stringi, stringr, tibble diff --git a/NAMESPACE b/NAMESPACE index a9e361f..1eb4fbc 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -8,3 +8,4 @@ export(qtr_end) export(qtr_next) export(qtr_prev) importFrom(magrittr,"%>%") +importFrom(rlang,.data) diff --git a/NEWS.md b/NEWS.md index a8aa2ae..d2be6d6 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,8 @@ -# phsmethods 0.1.1 (2020-01-29) -- `file_size()`, `fin_year()`, `qtr()`, `qtr_end()`, `qtr_next()` and `qtr_prev()` now use `inherits(x, "y")` instead of `class(x) == "y"` to check class. The reasoning is explained in this [blogpost by Martin Maechler](https://developer.r-project.org/Blog/public/2019/11/09/when-you-think-class.-think-again/index.html). +# phsmethods 0.1.1 (2020-02-10) + +- `file_size()`, `fin_year()`, `qtr()`, `qtr_end()`, `qtr_next()` and `qtr_prev()` now use `inherits(x, "y")` instead of `class(x) == "y"` to check class. The reasoning is explained in this [blogpost by Martin Maechler](https://developer.r-project.org/Blog/public/2019/11/09/when-you-think-class.-think-again/index.html). + +- The performance of `fin_year()` has been improved. The function now extracts the unique date(s) from the input, calculates the associated financial year(s), and joins to the original input. This is in contrast with the original method, which directly calculated the financial year of all input dates individually. # phsmethods 0.1.0 (2020-01-24) diff --git a/R/fin_year.R b/R/fin_year.R index fd05340..2376577 100644 --- a/R/fin_year.R +++ b/R/fin_year.R @@ -5,9 +5,9 @@ #' #' @details The PHS accepted format for financial year is yyyy/yy e.g. 2017/18. #' -#' @param date A date which must be supplied with \code{Date} class. The -#' functions as.Date() or lubridate::dmy() are examples of functions that can -#' be used to change a variable to date class. +#' @param date A date which must be supplied with \code{Date} or \code{POSIXct} +#' class. The functions as.Date(), lubridate::dmy() or as.POSIXct() are examples +#' of functions that can be used to change a variable to the appropriate class. #' #' @examples #' x <- lubridate::dmy(c(21012017, 04042017, 17112017)) @@ -17,14 +17,26 @@ #' @export fin_year <- function(date) { - if (!inherits(date, "Date")) { - stop("The input must have Date class.") + if (!inherits(date, c("Date", "POSIXct"))) { + stop("The input must have Date or POSIXct class.") } - paste0(ifelse(lubridate::month(date) >= 4, - lubridate::year(date), - lubridate::year(date) - 1), "/", - substr(ifelse(lubridate::month(date) >= 4, - lubridate::year(date) + 1, - lubridate::year(date)), 3, 4)) + # Simply converting all elements of the input vector resulted in poor + # performance for large vectors. The function was rewritten to extract + # a vector of unique elements from the input, convert those to financial year + # and then match them back on to the original input. This vastly improves + # performance for large inputs. + + tibble::tibble(dates = unique(date)) %>% + dplyr::mutate(fin_year = paste0(ifelse(lubridate::month(.data$dates) >= 4, + lubridate::year(.data$dates), + lubridate::year(.data$dates) - 1), + "/", + substr( + ifelse(lubridate::month(.data$dates) >= 4, + lubridate::year(.data$dates) + 1, + lubridate::year(.data$dates)), + 3, 4))) %>% + dplyr::right_join(tibble::tibble(dates = date), by = "dates") %>% + dplyr::pull(fin_year) } diff --git a/R/phsmethods.R b/R/phsmethods.R index 85c3a03..50086d6 100644 --- a/R/phsmethods.R +++ b/R/phsmethods.R @@ -7,6 +7,7 @@ #' @docType package #' @name phsmethods #' @importFrom magrittr %>% +#' @importFrom rlang .data NULL # Stops notes from appearing in R CMD check because of undefined global diff --git a/README.Rmd b/README.Rmd index 6b7dc46..a2a92f0 100644 --- a/README.Rmd +++ b/README.Rmd @@ -18,7 +18,7 @@ knitr::opts_chunk$set( [![Build Status](https://travis-ci.com/Health-SocialCare-Scotland/phsmethods.svg?branch=master)](https://travis-ci.com/Health-SocialCare-Scotland/phsmethods) [![codecov](https://codecov.io/gh/Health-SocialCare-Scotland/phsmethods/branch/master/graph/badge.svg)](https://codecov.io/gh/Health-SocialCare-Scotland/phsmethods) -`phsmethods` contains functions for commonly undertaken analytical tasks in [Public Health Scotland (PHS)](https://publichealthreform.scot/public-health-scotland): +`phsmethods` contains functions for commonly undertaken analytical tasks in [Public Health Scotland (PHS)](https://www.publichealthscotland.scot/): - `file_size()` returns the names and sizes of files in a directory - `fin_year()` assigns a date to a financial year in the format `YYYY/YY` diff --git a/README.md b/README.md index c105d42..ba44871 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Status](https://travis-ci.com/Health-SocialCare-Scotland/phsmethods.svg?branch=m `phsmethods` contains functions for commonly undertaken analytical tasks in [Public Health Scotland -(PHS)](https://publichealthreform.scot/public-health-scotland): +(PHS)](https://www.publichealthscotland.scot/): - `file_size()` returns the names and sizes of files in a directory - `fin_year()` assigns a date to a financial year in the format @@ -189,7 +189,7 @@ of them will conduct a review, provide feedback and, if necessary, request changes prior to merging your branch. Please be mindful of information governance when contributing to this -package. No data files (aside from publically available and downloadable +package. No data files (aside from publicly available and downloadable datasets or unless explicitly approved), server connection details, passwords or person identifiable or otherwise confidential information should be included anywhere within this package or any other repository diff --git a/man/fin_year.Rd b/man/fin_year.Rd index e16d76b..15e5f9f 100644 --- a/man/fin_year.Rd +++ b/man/fin_year.Rd @@ -7,9 +7,9 @@ fin_year(date) } \arguments{ -\item{date}{A date which must be supplied with \code{Date} class. The -functions as.Date() or lubridate::dmy() are examples of functions that can -be used to change a variable to date class.} +\item{date}{A date which must be supplied with \code{Date} or \code{POSIXct} +class. The functions as.Date(), lubridate::dmy() or as.POSIXct() are examples +of functions that can be used to change a variable to the appropriate class.} } \description{ \code{fin_year} takes a date and assigns it to the correct diff --git a/tests/testthat/test-fin_year.R b/tests/testthat/test-fin_year.R index 8af557e..c79af8c 100644 --- a/tests/testthat/test-fin_year.R +++ b/tests/testthat/test-fin_year.R @@ -3,12 +3,14 @@ context("test-fin_year") test_that("Date is assigned to the correct financial year", { expect_equal(fin_year(as.Date("20120331", "%Y%m%d")), "2011/12") expect_equal(fin_year(as.Date("20120401", "%Y%m%d")), "2012/13") + expect_equal(fin_year(as.POSIXct("20190104", format = "%Y%m%d")), "2018/19") }) test_that("Date is accepted in various formats", { expect_equal(fin_year(as.Date("17111993", "%d%m%Y")), "1993/94") expect_equal(fin_year(as.Date("19980404", "%Y%m%d")), "1998/99") expect_equal(fin_year(as.Date("21-Jan-2017", "%d-%B-%Y")), "2016/17") + expect_equal(fin_year(as.POSIXct("20181401", format = "%Y%d%m")), "2017/18") expect_equal(fin_year(lubridate::dmy(29102019)), "2019/20") })