├── vignettes ├── .gitignore ├── log_inc-log-cuminc-charts.Rmd ├── cumulative-cases.Rmd ├── changepoint.Rmd └── instant-reproduction-num.Rmd ├── .Rbuildignore ├── .gitignore ├── man ├── figures │ ├── README-plot-1.png │ └── README-highlight-selected-countries-1.png ├── pipe.Rd ├── covid_jhu_read.Rd ├── covid_jhu.Rd ├── diff_days.Rd ├── geom_covid_country_label.Rd ├── covid_jhu_pivot_longer.Rd ├── add_country_row_id.Rd ├── pluck_latest_ecdc.Rd ├── covid_jhu_clean_names.Rd ├── gg-covid.Rd ├── try_ecdc.Rd ├── augment_estimate_repro.Rd ├── country_repro_errors.Rd ├── covid_jhu_filter_countres.Rd ├── covid_high_incidence.Rd ├── covid_prepare_estimate_repro.Rd ├── extract_change_point_mean_var.Rd ├── covid_summarise_doubling.Rd ├── tidy_repro_estimate.Rd ├── extract_first_np_change_point.Rd ├── covid_ecdc.Rd ├── gg_effective_repro_incidence_patchwork.Rd ├── add_country_label.Rd ├── add_covid_change_point.Rd ├── summarise_country_over_limit.Rd ├── summarise_covid_global.Rd ├── covid_change_point.Rd ├── covid_highlight_australia_plus.Rd ├── filter_country_over_limit.Rd ├── add_days_since_limit.Rd ├── add_weekly_avg.Rd ├── effective-repro.Rd ├── add_country_hit_limit.Rd ├── gt-zero.Rd ├── covid-estimate-repro.Rd ├── gg_covid_cumulative_cases_deaths_exceed_limit.Rd ├── covid_latest.Rd ├── add_instant_reproduction.Rd ├── gg_covid_cumulative_exceed_limit.Rd ├── covid_estimate_repro.Rd ├── gg_covid_incidence_exceed_limit.Rd └── patch_data.Rd ├── R ├── summarise-cases.R ├── utils-pipe.R ├── add-country-row-id.R ├── country-global-incidence.R ├── add-weekly-avg.R ├── high-incidence.R ├── when-all-gt-zero.R ├── global-vars.R ├── aa-utils.R ├── observed-time-to-double.R ├── cutting-room.R ├── pull-covid-jhu.R ├── patch-data.R ├── changepoint.R ├── country-over-limit.R ├── pull-covid-cdc.R ├── estimate-instant-reproduction.R └── ggplot-helpers.R ├── NEWS.md ├── covidrecon.Rproj ├── DESCRIPTION ├── NAMESPACE ├── README.Rmd ├── README.md └── LICENSE /vignettes/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | *.R 3 | -------------------------------------------------------------------------------- /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^README\.Rmd$ 4 | ^\.cache$ 5 | ^\.covid_cache$ 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | inst/doc 6 | .cache/ 7 | .covid_cache 8 | -------------------------------------------------------------------------------- /man/figures/README-plot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CBDRH/covidrecon/HEAD/man/figures/README-plot-1.png -------------------------------------------------------------------------------- /man/figures/README-highlight-selected-countries-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CBDRH/covidrecon/HEAD/man/figures/README-highlight-selected-countries-1.png -------------------------------------------------------------------------------- /R/summarise-cases.R: -------------------------------------------------------------------------------- 1 | summarise_incident_cumulative <- function(data){ 2 | data %>% 3 | summarise(incident_cases = sum(incident_cases), 4 | cumulative_cases = sum(cumulative_cases)) 5 | } 6 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # covidrecon 0.0.0.9000 2 | 3 | * Added a `NEWS.md` file to track changes to the package. 4 | * `add_weekly_avg` computes the weekly average of a given variable 5 | * added `summarise_covid_doubling`, which computes observed time to 6 | double covid19 cases 7 | -------------------------------------------------------------------------------- /R/utils-pipe.R: -------------------------------------------------------------------------------- 1 | #' Pipe operator 2 | #' 3 | #' See \code{magrittr::\link[magrittr:pipe]{\%>\%}} for details. 4 | #' 5 | #' @name %>% 6 | #' @rdname pipe 7 | #' @keywords internal 8 | #' @export 9 | #' @importFrom magrittr %>% 10 | #' @usage lhs \%>\% rhs 11 | NULL 12 | -------------------------------------------------------------------------------- /man/pipe.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils-pipe.R 3 | \name{\%>\%} 4 | \alias{\%>\%} 5 | \title{Pipe operator} 6 | \usage{ 7 | lhs \%>\% rhs 8 | } 9 | \description{ 10 | See \code{magrittr::\link[magrittr:pipe]{\%>\%}} for details. 11 | } 12 | \keyword{internal} 13 | -------------------------------------------------------------------------------- /man/covid_jhu_read.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/pull-covid-jhu.R 3 | \name{covid_jhu_read} 4 | \alias{covid_jhu_read} 5 | \title{read in raw covid19 data} 6 | \usage{ 7 | covid_jhu_read() 8 | } 9 | \value{ 10 | dataframe 11 | } 12 | \description{ 13 | read in raw covid19 data 14 | } 15 | -------------------------------------------------------------------------------- /man/covid_jhu.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/pull-covid-jhu.R 3 | \name{covid_jhu} 4 | \alias{covid_jhu} 5 | \title{Pulls and tidies the latest covid19 data} 6 | \usage{ 7 | covid_jhu() 8 | } 9 | \value{ 10 | covid19 data with columns.. 11 | } 12 | \description{ 13 | Pulls and tidies the latest covid19 data 14 | } 15 | -------------------------------------------------------------------------------- /R/add-country-row-id.R: -------------------------------------------------------------------------------- 1 | #' Add row ID for each country from start date 2 | #' 3 | #' @param covid_data covid19 data 4 | #' 5 | #' @return adds row ID column, `n_days`, for each country 6 | #' @export 7 | add_country_row_id <- function(covid_data){ 8 | covid_data %>% 9 | dplyr::arrange(geo_id, date) %>% 10 | dplyr::group_by(geo_id) %>% 11 | dplyr::mutate(n_days = dplyr::row_number()) %>% 12 | dplyr::ungroup() 13 | } 14 | -------------------------------------------------------------------------------- /man/diff_days.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/aa-utils.R 3 | \name{diff_days} 4 | \alias{diff_days} 5 | \title{Difference in days between two dates} 6 | \usage{ 7 | diff_days(x, y) 8 | } 9 | \arguments{ 10 | \item{x}{first date} 11 | 12 | \item{y}{second date} 13 | } 14 | \value{ 15 | numeric number of days 16 | } 17 | \description{ 18 | Difference in days between two dates 19 | } 20 | -------------------------------------------------------------------------------- /covidrecon.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: knitr 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Package 19 | PackageUseDevtools: Yes 20 | PackageInstallArgs: --no-multiarch --with-keep.source 21 | -------------------------------------------------------------------------------- /man/geom_covid_country_label.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/cutting-room.R 3 | \name{geom_covid_country_label} 4 | \alias{geom_covid_country_label} 5 | \title{Adds nice country labels to ggplot, based on \code{add_country_label()}} 6 | \usage{ 7 | geom_covid_country_label() 8 | } 9 | \value{ 10 | ggplot label added to ggplot 11 | } 12 | \description{ 13 | Adds nice country labels to ggplot, based on \code{add_country_label()} 14 | } 15 | -------------------------------------------------------------------------------- /man/covid_jhu_pivot_longer.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/pull-covid-jhu.R 3 | \name{covid_jhu_pivot_longer} 4 | \alias{covid_jhu_pivot_longer} 5 | \title{pivots the covid19 data into longer form} 6 | \usage{ 7 | covid_jhu_pivot_longer(x) 8 | } 9 | \arguments{ 10 | \item{x}{data that has been imported and cleaned} 11 | } 12 | \value{ 13 | longer form pivoted data 14 | } 15 | \description{ 16 | pivots the covid19 data into longer form 17 | } 18 | -------------------------------------------------------------------------------- /man/add_country_row_id.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/add-country-row-id.R 3 | \name{add_country_row_id} 4 | \alias{add_country_row_id} 5 | \title{Add row ID for each country from start date} 6 | \usage{ 7 | add_country_row_id(covid_data) 8 | } 9 | \arguments{ 10 | \item{covid_data}{covid19 data} 11 | } 12 | \value{ 13 | adds row ID column, \code{n_days}, for each country 14 | } 15 | \description{ 16 | Add row ID for each country from start date 17 | } 18 | -------------------------------------------------------------------------------- /man/pluck_latest_ecdc.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/pull-covid-cdc.R 3 | \name{pluck_latest_ecdc} 4 | \alias{pluck_latest_ecdc} 5 | \title{Pluck the latest ecdc data} 6 | \usage{ 7 | pluck_latest_ecdc(data) 8 | } 9 | \arguments{ 10 | \item{data}{covid19 list of latest data pulled from \code{try_ecdc}.} 11 | } 12 | \value{ 13 | single data.frame 14 | } 15 | \description{ 16 | For internal use within covid19 extraction data 17 | } 18 | \note{ 19 | internal 20 | } 21 | -------------------------------------------------------------------------------- /man/covid_jhu_clean_names.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/pull-covid-jhu.R 3 | \name{covid_jhu_clean_names} 4 | \alias{covid_jhu_clean_names} 5 | \title{clean variable names of covid19 raw data (from \code{covid_read})} 6 | \usage{ 7 | covid_jhu_clean_names(x) 8 | } 9 | \arguments{ 10 | \item{x}{covid19 raw data} 11 | } 12 | \value{ 13 | data.frame with tidied names 14 | } 15 | \description{ 16 | clean variable names of covid19 raw data (from \code{covid_read}) 17 | } 18 | -------------------------------------------------------------------------------- /man/gg-covid.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ggplot-helpers.R 3 | \name{gg_covid_cases} 4 | \alias{gg_covid_cases} 5 | \alias{gg-covid} 6 | \alias{gg_covid_cumulative_cases} 7 | \title{misc-ggplot funs for covid19} 8 | \usage{ 9 | gg_covid_cases(covid_data) 10 | 11 | gg_covid_cumulative_cases(covid_data) 12 | } 13 | \arguments{ 14 | \item{covid_data}{covid19 data} 15 | } 16 | \value{ 17 | ggplot image 18 | } 19 | \description{ 20 | misc-ggplot funs for covid19 21 | } 22 | -------------------------------------------------------------------------------- /man/try_ecdc.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/pull-covid-cdc.R 3 | \name{try_ecdc} 4 | \alias{try_ecdc} 5 | \title{Downloads both yesterday and today's COVID19 data} 6 | \usage{ 7 | try_ecdc(memoise = TRUE) 8 | } 9 | \arguments{ 10 | \item{memoise}{do you want to memoise (cache the data?). Default is TRUE} 11 | } 12 | \value{ 13 | list of yesterdays and today's COVID19 data 14 | } 15 | \description{ 16 | Assuming CET time zones. For use within \code{latest_covid()}. 17 | } 18 | -------------------------------------------------------------------------------- /man/augment_estimate_repro.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/estimate-instant-reproduction.R 3 | \name{augment_estimate_repro} 4 | \alias{augment_estimate_repro} 5 | \title{Tidies output of \code{estimate_repro_all}} 6 | \usage{ 7 | augment_estimate_repro(covid_data_estimated) 8 | } 9 | \arguments{ 10 | \item{covid_data_estimated}{covid19 data estimated with \code{estimate_repro_all}} 11 | } 12 | \value{ 13 | data.frame 14 | } 15 | \description{ 16 | Tidies output of \code{estimate_repro_all} 17 | } 18 | -------------------------------------------------------------------------------- /man/country_repro_errors.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/estimate-instant-reproduction.R 3 | \name{country_repro_errors} 4 | \alias{country_repro_errors} 5 | \title{Extract (any) errors from \code{estimate_repro_all}} 6 | \usage{ 7 | country_repro_errors(covid_data_estimated) 8 | } 9 | \arguments{ 10 | \item{covid_data_estimated}{data from \code{estimate_repro_all}} 11 | } 12 | \value{ 13 | vector of error messages 14 | } 15 | \description{ 16 | Extract (any) errors from \code{estimate_repro_all} 17 | } 18 | -------------------------------------------------------------------------------- /man/covid_jhu_filter_countres.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/pull-covid-jhu.R 3 | \name{covid_jhu_filter_countres} 4 | \alias{covid_jhu_filter_countres} 5 | \title{Filter covid countries to provided countries} 6 | \usage{ 7 | covid_jhu_filter_countres(data, countries) 8 | } 9 | \arguments{ 10 | \item{data}{covid19 data} 11 | 12 | \item{countries}{vector of countries} 13 | } 14 | \value{ 15 | dataset filtered to existing countries 16 | } 17 | \description{ 18 | Filter covid countries to provided countries 19 | } 20 | -------------------------------------------------------------------------------- /man/covid_high_incidence.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/high-incidence.R 3 | \name{covid_high_incidence} 4 | \alias{covid_high_incidence} 5 | \title{Return only countries that have more than some limit} 6 | \usage{ 7 | covid_high_incidence(covid_data, limit = 100) 8 | } 9 | \arguments{ 10 | \item{covid_data}{data pulled from \code{covid_pull_data()}} 11 | 12 | \item{limit}{when countries hit some limit. default is 100} 13 | } 14 | \value{ 15 | high incidence data 16 | } 17 | \description{ 18 | Return only countries that have more than some limit 19 | } 20 | -------------------------------------------------------------------------------- /man/covid_prepare_estimate_repro.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/estimate-instant-reproduction.R 3 | \name{covid_prepare_estimate_repro} 4 | \alias{covid_prepare_estimate_repro} 5 | \title{Prepare covid19 data for estimating instant repro number} 6 | \usage{ 7 | covid_prepare_estimate_repro(covid_data) 8 | } 9 | \arguments{ 10 | \item{covid_data}{covid19 data} 11 | } 12 | \value{ 13 | dataframe with columns "dates" and "I", ready for 14 | \code{EpiEstim::estimate_R} 15 | } 16 | \description{ 17 | Prepare covid19 data for estimating instant repro number 18 | } 19 | -------------------------------------------------------------------------------- /man/extract_change_point_mean_var.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/changepoint.R 3 | \name{extract_change_point_mean_var} 4 | \alias{extract_change_point_mean_var} 5 | \title{Extract changepoint} 6 | \usage{ 7 | extract_change_point_mean_var(data, x = "cases", ...) 8 | } 9 | \arguments{ 10 | \item{data}{data.frame} 11 | 12 | \item{x}{variable name (as character) of cases. Default is "cases".} 13 | 14 | \item{...}{params to pass to \code{changepoint::cpt.meanvar}} 15 | } 16 | \value{ 17 | changepoint vars 18 | } 19 | \description{ 20 | Extract changepoint 21 | } 22 | -------------------------------------------------------------------------------- /R/country-global-incidence.R: -------------------------------------------------------------------------------- 1 | #' Summarise covid19 data to cases over time globally 2 | #' 3 | #' Requires that incidence cases are called `cases`, country is called 4 | #' `country_region`, and date is called `date`. 5 | #' 6 | #' @param covid_data covid19 data 7 | #' 8 | #' @return data.frame with covid19 cases, columns called 9 | #' `date`, `cases`, and `cumulative_cases`. 10 | #' @export 11 | summarise_covid_global <- function(covid_data){ 12 | covid_data %>% 13 | dplyr::group_by(date) %>% 14 | dplyr::summarise(cases = sum(cases), 15 | cumulative_cases = sum(cumulative_cases)) 16 | } 17 | -------------------------------------------------------------------------------- /man/covid_summarise_doubling.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/observed-time-to-double.R 3 | \name{covid_summarise_doubling} 4 | \alias{covid_summarise_doubling} 5 | \title{Calculate the time to double covid19 data} 6 | \usage{ 7 | covid_summarise_doubling(covid_data) 8 | } 9 | \arguments{ 10 | \item{covid_data}{covid19 data} 11 | } 12 | \value{ 13 | data of country region, with \code{days_to_double}, and \code{double_target} 14 | being the "from x number of cases" 15 | } 16 | \description{ 17 | Calculate the time to double covid19 data 18 | } 19 | \author{ 20 | Miles McBain 21 | } 22 | -------------------------------------------------------------------------------- /man/tidy_repro_estimate.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/estimate-instant-reproduction.R 3 | \name{tidy_repro_estimate} 4 | \alias{tidy_repro_estimate} 5 | \title{Tidies up output from \code{EpiEstim::estimate_R}} 6 | \usage{ 7 | tidy_repro_estimate(covid_estimated_reproduction) 8 | } 9 | \arguments{ 10 | \item{covid_estimated_reproduction}{output from \code{EpiEstim::estimate_R}} 11 | } 12 | \value{ 13 | returns columns on estiamted instantaneous reproduction, and quantiles, 14 | as well as dates. 15 | } 16 | \description{ 17 | Tidies up output from \code{EpiEstim::estimate_R} 18 | } 19 | -------------------------------------------------------------------------------- /man/extract_first_np_change_point.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/changepoint.R 3 | \name{extract_first_np_change_point} 4 | \alias{extract_first_np_change_point} 5 | \title{Extract non-parametric changepoint} 6 | \usage{ 7 | extract_first_np_change_point(data, x = "cases", ...) 8 | } 9 | \arguments{ 10 | \item{data}{data.frame} 11 | 12 | \item{x}{variable name (as character) of cases. Default is "cases".} 13 | 14 | \item{...}{params to pass to \code{changepoint.np::cpt.np}} 15 | } 16 | \value{ 17 | changepoint vars 18 | } 19 | \description{ 20 | Extract non-parametric changepoint 21 | } 22 | -------------------------------------------------------------------------------- /man/covid_ecdc.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/pull-covid-cdc.R 3 | \name{covid_ecdc} 4 | \alias{covid_ecdc} 5 | \title{Download raw COVID19 data from European CDC} 6 | \usage{ 7 | covid_ecdc(date) 8 | } 9 | \arguments{ 10 | \item{date}{in format "YYYY-MM-DD". So, "2020-01-01" is 1st Jan, 2020} 11 | } 12 | \value{ 13 | data.frame 14 | } 15 | \description{ 16 | This function will download raw COVID19 data, given a date. 17 | It will error if you enter a date that is later than the current date 18 | on the CDC site. See \code{latest_covid()} for a function that handles 19 | the full details of this. 20 | } 21 | -------------------------------------------------------------------------------- /man/gg_effective_repro_incidence_patchwork.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ggplot-helpers.R 3 | \name{gg_effective_repro_incidence_patchwork} 4 | \alias{gg_effective_repro_incidence_patchwork} 5 | \title{Effective Reproductive pathwork} 6 | \usage{ 7 | gg_effective_repro_incidence_patchwork(covid_effective_r, covid_data, country) 8 | } 9 | \arguments{ 10 | \item{covid_effective_r}{covid19 data with effective repro added with 11 | \code{covid_estimate_repro()}.} 12 | 13 | \item{covid_data}{covid19 data} 14 | 15 | \item{country}{country to display} 16 | } 17 | \description{ 18 | Effective Reproductive pathwork 19 | } 20 | -------------------------------------------------------------------------------- /man/add_country_label.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/cutting-room.R 3 | \name{add_country_label} 4 | \alias{add_country_label} 5 | \title{Add a country label for plotting} 6 | \usage{ 7 | add_country_label(data, countries = unique(data$country_region)) 8 | } 9 | \arguments{ 10 | \item{data}{covid19 data} 11 | 12 | \item{countries}{default adds all countries. Otherwise, they are 13 | specified with character vector.} 14 | } 15 | \value{ 16 | data.frame with added columns of selected countries 17 | } 18 | \description{ 19 | This adds the appropriate lables for each country, to assist plotting 20 | with geom_label 21 | } 22 | -------------------------------------------------------------------------------- /man/add_covid_change_point.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/changepoint.R 3 | \name{add_covid_change_point} 4 | \alias{add_covid_change_point} 5 | \title{Adds changepoint date based on \code{changepoint.np::cpt.np}} 6 | \usage{ 7 | add_covid_change_point(covid_data, x = "cases", ...) 8 | } 9 | \arguments{ 10 | \item{covid_data}{data.frame} 11 | 12 | \item{x}{variable name (as character) of cases. Default is "cases".} 13 | 14 | \item{...}{params to pass to \code{changepoint.np::cpt.np}} 15 | } 16 | \value{ 17 | ggplot2 plot 18 | } 19 | \description{ 20 | Adds changepoint date based on \code{changepoint.np::cpt.np} 21 | } 22 | -------------------------------------------------------------------------------- /man/summarise_country_over_limit.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/country-over-limit.R 3 | \name{summarise_country_over_limit} 4 | \alias{summarise_country_over_limit} 5 | \title{Create a summary for each country, and a flag of whether they are over limit} 6 | \usage{ 7 | summarise_country_over_limit(covid_data, limit = 100) 8 | } 9 | \arguments{ 10 | \item{covid_data}{covid19 data} 11 | 12 | \item{limit}{limit} 13 | } 14 | \value{ 15 | data.frame with two columns, \code{country_region} and \code{over_limit} 16 | } 17 | \description{ 18 | Create a summary for each country, and a flag of whether they are over limit 19 | } 20 | -------------------------------------------------------------------------------- /man/summarise_covid_global.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/country-global-incidence.R 3 | \name{summarise_covid_global} 4 | \alias{summarise_covid_global} 5 | \title{Summarise covid19 data to cases over time globally} 6 | \usage{ 7 | summarise_covid_global(covid_data) 8 | } 9 | \arguments{ 10 | \item{covid_data}{covid19 data} 11 | } 12 | \value{ 13 | data.frame with covid19 cases, columns called 14 | \code{date}, \code{cases}, and \code{cumulative_cases}. 15 | } 16 | \description{ 17 | Requires that incidence cases are called \code{cases}, country is called 18 | \code{country_region}, and date is called \code{date}. 19 | } 20 | -------------------------------------------------------------------------------- /man/covid_change_point.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/changepoint.R 3 | \name{covid_change_point} 4 | \alias{covid_change_point} 5 | \title{Calculate changepoint date using \code{changepoint::cpt.meanvar}} 6 | \usage{ 7 | covid_change_point(covid_data, x = "cases", ...) 8 | } 9 | \arguments{ 10 | \item{covid_data}{data.frame} 11 | 12 | \item{x}{variable name (as character) of cases. Default is "cases".} 13 | 14 | \item{...}{params to pass to \code{changepoint::cpt.meanvar}} 15 | } 16 | \value{ 17 | data.frame of changepoints 18 | } 19 | \description{ 20 | Calculate changepoint date using \code{changepoint::cpt.meanvar} 21 | } 22 | -------------------------------------------------------------------------------- /man/covid_highlight_australia_plus.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/cutting-room.R 3 | \name{covid_highlight_australia_plus} 4 | \alias{covid_highlight_australia_plus} 5 | \title{Add alpha column which will highlight australia foremost, then ohters} 6 | \usage{ 7 | covid_highlight_australia_plus(data, plus = "Canada") 8 | } 9 | \arguments{ 10 | \item{data}{covid19 data} 11 | 12 | \item{plus}{additional countries to highlight. Defaults to just Canada.} 13 | } 14 | \value{ 15 | data with added column "alpha" with extra info 16 | } 17 | \description{ 18 | Add alpha column which will highlight australia foremost, then ohters 19 | } 20 | -------------------------------------------------------------------------------- /man/filter_country_over_limit.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/country-over-limit.R 3 | \name{filter_country_over_limit} 4 | \alias{filter_country_over_limit} 5 | \title{Filter data to only include countries that have more than a certain number 6 | of cases} 7 | \usage{ 8 | filter_country_over_limit(covid_data, limit = 100) 9 | } 10 | \arguments{ 11 | \item{covid_data}{covid19 data} 12 | 13 | \item{limit}{number of cases - default over 100} 14 | } 15 | \value{ 16 | data.frame with covid data that has more than 100 cases 17 | } 18 | \description{ 19 | Filter data to only include countries that have more than a certain number 20 | of cases 21 | } 22 | -------------------------------------------------------------------------------- /man/add_days_since_limit.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/country-over-limit.R 3 | \name{add_days_since_limit} 4 | \alias{add_days_since_limit} 5 | \title{Add a column of the days since some limit of cumulative cases is reached} 6 | \usage{ 7 | add_days_since_limit(covid_data, limit = 100) 8 | } 9 | \arguments{ 10 | \item{covid_data}{covid19 data} 11 | 12 | \item{limit}{limit for flagging} 13 | } 14 | \value{ 15 | data.frame with extra column, "days_since_limit", which contains 16 | the number of days since the cumulative cases reached 100. 17 | } 18 | \description{ 19 | Add a column of the days since some limit of cumulative cases is reached 20 | } 21 | -------------------------------------------------------------------------------- /man/add_weekly_avg.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/add-weekly-avg.R 3 | \name{add_weekly_avg} 4 | \alias{add_weekly_avg} 5 | \title{Add Weekly average summary, for each country} 6 | \usage{ 7 | add_weekly_avg(covid, ...) 8 | } 9 | \arguments{ 10 | \item{covid}{covid19 data} 11 | 12 | \item{...}{variables to compute weekly average of} 13 | } 14 | \value{ 15 | data frame with weekly average computed 16 | } 17 | \description{ 18 | Add Weekly average summary, for each country 19 | } 20 | \examples{ 21 | \dontrun{ 22 | covid <- covid_latest() 23 | add_weekly_avg(covid, cases) 24 | add_weekly_avg(covid, deaths) 25 | add_weekly_avg(covid, cases, deaths) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /man/effective-repro.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ggplot-helpers.R 3 | \name{gg_effective_repro_all} 4 | \alias{gg_effective_repro_all} 5 | \alias{effective-repro} 6 | \alias{gg_effective_repro_facet} 7 | \title{Plot effective reproduction number} 8 | \usage{ 9 | gg_effective_repro_all(covid_effective_r, highlight = "Australia") 10 | 11 | gg_effective_repro_facet(covid_effective_r) 12 | } 13 | \arguments{ 14 | \item{covid_effective_r}{covid19 data with estimated effective R} 15 | 16 | \item{highlight}{character vector of countries to highlight. Default, "Australia"} 17 | } 18 | \value{ 19 | ggplot2 plot 20 | } 21 | \description{ 22 | Plot effective reproduction number 23 | } 24 | -------------------------------------------------------------------------------- /R/add-weekly-avg.R: -------------------------------------------------------------------------------- 1 | #' Add Weekly average summary, for each country 2 | #' 3 | #' @param covid covid19 data 4 | #' @param ... variables to compute weekly average of 5 | #' 6 | #' @return data frame with weekly average computed 7 | #' @export 8 | #' @examples 9 | #' \dontrun{ 10 | #' covid <- covid_latest() 11 | #' add_weekly_avg(covid, cases) 12 | #' add_weekly_avg(covid, deaths) 13 | #' add_weekly_avg(covid, cases, deaths) 14 | #' } 15 | add_weekly_avg <- function(covid, ...){ 16 | dots <- rlang::enquos(...) 17 | covid %>% 18 | dplyr::mutate(week = lubridate::week(date)) %>% 19 | dplyr::group_by(country_region, week) %>% 20 | # mutate_at(vars(cases, deaths), list(avg_weekly = mean)) %>% 21 | dplyr::mutate_at(dplyr::vars(!!!dots), list(avg_weekly = mean)) %>% 22 | dplyr::ungroup() 23 | } 24 | -------------------------------------------------------------------------------- /man/add_country_hit_limit.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/country-over-limit.R 3 | \name{add_country_hit_limit} 4 | \alias{add_country_hit_limit} 5 | \title{Add a column that indicates when a country hits a limit of cases} 6 | \usage{ 7 | add_country_hit_limit(covid_data, limit = 100) 8 | } 9 | \arguments{ 10 | \item{covid_data}{covid19 data with cumulative cases for each country} 11 | 12 | \item{limit}{defaults to 100} 13 | } 14 | \value{ 15 | data.frame with additional column "hit limit" indicating the day 16 | a country passed that limit 17 | } 18 | \description{ 19 | Requires that country is called \code{country_region}, date is called \code{date}, 20 | cumulative cases are called \code{cumulative_cases}. 21 | } 22 | \examples{ 23 | # covid \%>\% 24 | } 25 | -------------------------------------------------------------------------------- /man/gt-zero.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/when-all-gt-zero.R 3 | \name{when_all_gt} 4 | \alias{when_all_gt} 5 | \alias{gt-zero} 6 | \alias{where_all_gt} 7 | \alias{when_all_gte} 8 | \alias{where_all_gte} 9 | \title{Determine when all numbers in a vector are greater than zero} 10 | \usage{ 11 | when_all_gt(x, num = 0) 12 | 13 | where_all_gt(x, num = 0) 14 | 15 | when_all_gte(x, num = 0) 16 | 17 | where_all_gte(x, num = 0) 18 | } 19 | \arguments{ 20 | \item{x}{numeric vector} 21 | 22 | \item{num}{greater than some number, default 0} 23 | } 24 | \value{ 25 | logical vector - TRUE when all numbers start to be GT zero 26 | } 27 | \description{ 28 | Determine when all numbers in a vector are greater than zero 29 | } 30 | \examples{ 31 | when_all_gt(c(0, 1, 0, 1, 1, 2, 3)) 32 | when_all_gt(c(0, 0, 0, 0)) 33 | when_all_gt(c(1, 0, 1, 1, 0, 2, 3, 4)) 34 | where_all_gt(c(1, 0, 1, 1, 0, 2, 3, 4)) 35 | } 36 | -------------------------------------------------------------------------------- /man/covid-estimate-repro.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/estimate-instant-reproduction.R 3 | \name{covid-estimate-repro} 4 | \alias{covid-estimate-repro} 5 | \alias{estimate_repro_all} 6 | \title{Fits instant reproduction for each country} 7 | \usage{ 8 | estimate_repro_all( 9 | covid_data, 10 | estimate_method = "parametric_si", 11 | si_sample = NULL, 12 | config = list(mean_si = 4.7, std_si = 2.9) 13 | ) 14 | } 15 | \arguments{ 16 | \item{covid_data}{covid19 data} 17 | 18 | \item{estimate_method}{default is "parametric_si"} 19 | 20 | \item{si_sample}{SI samples. Default is NULL.} 21 | 22 | \item{config}{named list of values to pass to EpiEstim::make_config. Default 23 | is \code{mean_si = 4.7}, and \code{std_si = 2.9}.} 24 | } 25 | \value{ 26 | data.frame with several list columns containing various output of 27 | \code{EpiEstim::estimate_R}. 28 | } 29 | \description{ 30 | Fits instant reproduction for each country 31 | } 32 | -------------------------------------------------------------------------------- /man/gg_covid_cumulative_cases_deaths_exceed_limit.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ggplot-helpers.R 3 | \name{gg_covid_cumulative_cases_deaths_exceed_limit} 4 | \alias{gg_covid_cumulative_cases_deaths_exceed_limit} 5 | \title{Base plot for creating cumulative cases vs deaths of covid19 data} 6 | \usage{ 7 | gg_covid_cumulative_cases_deaths_exceed_limit( 8 | covid_data_limit, 9 | limit = NULL, 10 | highlight = "Australia" 11 | ) 12 | } 13 | \arguments{ 14 | \item{covid_data_limit}{\itemize{ 15 | \item covid19 with added limit 16 | (from \code{\link[=add_days_since_limit]{add_days_since_limit()}}) 17 | }} 18 | 19 | \item{limit}{the number of days since reached a limit (added for 20 | titling graphic). Default is 100.} 21 | 22 | \item{highlight}{the name of the country to highlight, default is Australia.} 23 | } 24 | \value{ 25 | ggplot plot 26 | } 27 | \description{ 28 | Base plot for creating cumulative cases vs deaths of covid19 data 29 | } 30 | -------------------------------------------------------------------------------- /man/covid_latest.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/pull-covid-cdc.R 3 | \name{covid_latest} 4 | \alias{covid_latest} 5 | \title{Pull latest covid19 data from European CDC} 6 | \usage{ 7 | covid_latest(patch = TRUE, memoise = TRUE, check_australia = TRUE) 8 | } 9 | \arguments{ 10 | \item{patch}{logical. Patch China miscounts see \code{\link[=patch_data]{patch_data()}}. 11 | Default is TRUE.} 12 | 13 | \item{memoise}{do you want to memoise (cache the data?). Default is TRUE. 14 | This caches the data into \code{.covid_cache}} 15 | 16 | \item{check_australia}{\itemize{ 17 | \item do you want to check if Australia has been given 18 | zero cases for the latest day (since March 16), and if so, replace 19 | those recent days with NA? Default is TRUE 20 | }} 21 | } 22 | \value{ 23 | data.frame 24 | } 25 | \description{ 26 | This pull data from \url{https://www.ecdc.europa.eu/en/publications-data/download-todays-data-geographic-distribution-covid-19-cases-worldwide}. 27 | } 28 | -------------------------------------------------------------------------------- /R/high-incidence.R: -------------------------------------------------------------------------------- 1 | #' Return only countries that have more than some limit 2 | #' 3 | #' @param covid_data data pulled from `covid_pull_data()` 4 | #' @param limit when countries hit some limit. default is 100 5 | #' 6 | #' @return high incidence data 7 | #' @export 8 | covid_high_incidence <- function(covid_data, limit = 100) { 9 | 10 | high_incidence_countries <- covid_data %>% 11 | filter_country_over_limit(limit = limit) %>% 12 | add_country_row_id() 13 | 14 | days_start_limit <- high_incidence_countries %>% 15 | dplyr::filter(hit_limit) %>% 16 | dplyr::select(geo_id, 17 | # the number of days since it started at limit 18 | day_start_limit = n_days) 19 | 20 | dplyr::left_join(x = high_incidence_countries, 21 | y = days_start_limit, 22 | by = "geo_id") %>% 23 | dplyr::mutate(date_since_limit_cases = n_days - day_start_limit) %>% 24 | dplyr::select(-over_limit, 25 | -day_start_limit, 26 | -hit_limit) 27 | 28 | } 29 | -------------------------------------------------------------------------------- /man/add_instant_reproduction.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/estimate-instant-reproduction.R 3 | \name{add_instant_reproduction} 4 | \alias{add_instant_reproduction} 5 | \title{Add instant reproduction number measures to provided covid19 data} 6 | \usage{ 7 | add_instant_reproduction( 8 | covid_data, 9 | estimate_method = "parametric_si", 10 | si_sample = NULL, 11 | config = list(mean_si = 4.7, std_si = 2.9) 12 | ) 13 | } 14 | \arguments{ 15 | \item{covid_data}{covid19 data} 16 | 17 | \item{estimate_method}{default is "parametric_si"} 18 | 19 | \item{si_sample}{SI samples. Default is NULL.} 20 | 21 | \item{config}{named list of values to pass to EpiEstim::make_config. Default 22 | is \code{mean_si = 4.7}, and \code{std_si = 2.9}.} 23 | } 24 | \value{ 25 | data.frame with covid19 columns plus output of \code{EpiEstim::estimate_R} 26 | and columns on estimated mean R values and quantiles etc. 27 | } 28 | \description{ 29 | Add instant reproduction number measures to provided covid19 data 30 | } 31 | -------------------------------------------------------------------------------- /R/when-all-gt-zero.R: -------------------------------------------------------------------------------- 1 | #' Determine when all numbers in a vector are greater than zero 2 | #' 3 | #' @param x numeric vector 4 | #' @param num greater than some number, default 0 5 | #' 6 | #' @return logical vector - TRUE when all numbers start to be GT zero 7 | #' @export 8 | #' 9 | #' @rdname gt-zero 10 | #' @examples 11 | #' when_all_gt(c(0, 1, 0, 1, 1, 2, 3)) 12 | #' when_all_gt(c(0, 0, 0, 0)) 13 | #' when_all_gt(c(1, 0, 1, 1, 0, 2, 3, 4)) 14 | #' where_all_gt(c(1, 0, 1, 1, 0, 2, 3, 4)) 15 | when_all_gt <- function(x, num = 0){ 16 | purrr::accumulate(x > num, 17 | .f = all, 18 | .dir = "backward") 19 | } 20 | 21 | #' @export 22 | #' @name gt-zero 23 | where_all_gt <- function(x, num = 0){ 24 | which(when_all_gt(x, num))[1] 25 | } 26 | 27 | #' @export 28 | #' @name gt-zero 29 | when_all_gte <- function(x, num = 0){ 30 | purrr::accumulate(x >= num, 31 | .f = all, 32 | .dir = "backward") 33 | } 34 | 35 | #' @export 36 | #' @name gt-zero 37 | where_all_gte <- function(x, num = 0){ 38 | which(when_all_gte(x, num))[1] 39 | } 40 | -------------------------------------------------------------------------------- /man/gg_covid_cumulative_exceed_limit.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ggplot-helpers.R 3 | \name{gg_covid_cumulative_exceed_limit} 4 | \alias{gg_covid_cumulative_exceed_limit} 5 | \title{Base plot for creating cumulative cases of covid19 data} 6 | \usage{ 7 | gg_covid_cumulative_exceed_limit( 8 | covid_data_limit, 9 | limit = NULL, 10 | highlight = "Australia" 11 | ) 12 | } 13 | \arguments{ 14 | \item{covid_data_limit}{\itemize{ 15 | \item covid19 with added limit 16 | (from \code{\link[=add_days_since_limit]{add_days_since_limit()}}) 17 | }} 18 | 19 | \item{limit}{the number of days since reached a limit (added for 20 | titling graphic). Default is 100.} 21 | 22 | \item{highlight}{the name of the country to highlight, default is Australia.} 23 | } 24 | \value{ 25 | ggplot plot 26 | } 27 | \description{ 28 | Base plot for creating cumulative cases of covid19 data 29 | } 30 | \examples{ 31 | \dontrun{ 32 | covid_data_since <- covid_data \%>\% 33 | add_days_since_limit(limit = 100) \%>\% 34 | dplyr::filter(days_since_limit >= 0) \%>\% 35 | dplyr::filter(country_region \%in\% c("Australia", "New Zealand")) 36 | 37 | gg_covid_cumulative_exceed_limit(covid_data_since) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: covidrecon 2 | Title: Pulls and Analyses COVID data 3 | Version: 0.0.0.9000 4 | Authors@R: c( 5 | person(given = "Timothy", 6 | family = "Churches", 7 | role = "aut"), 8 | person(given = "Nicholas", 9 | family = "Tierney", 10 | role = c("aut", "cre"), 11 | email = "nicholas.tierney@gmail.com", 12 | comment = c(ORCID = "https://orcid.org/0000-0003-1460-8722")) 13 | ) 14 | Description: Provides tools for getting COVID19 data, performing data analysis 15 | and doing data visualisations. 16 | License: MIT + file LICENSE 17 | Encoding: UTF-8 18 | Language: es 19 | LazyData: true 20 | Roxygen: list(markdown = TRUE) 21 | Imports: 22 | readr, 23 | tibble, 24 | dplyr, 25 | tidyr, 26 | stringr, 27 | lubridate, 28 | magrittr, 29 | countrycode, 30 | janitor, 31 | stats, 32 | scales, 33 | readxl, 34 | httr, 35 | glue, 36 | purrr, 37 | rlang, 38 | ggplot2, 39 | EpiEstim, 40 | changepoint, 41 | ggrepel, 42 | vctrs, 43 | memoise, 44 | changepoint.np, 45 | Suggests: 46 | knitr, 47 | rmarkdown, 48 | patchwork, 49 | gghighlight 50 | VignetteBuilder: knitr 51 | RoxygenNote: 7.1.0 52 | -------------------------------------------------------------------------------- /man/covid_estimate_repro.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/estimate-instant-reproduction.R 3 | \name{covid_estimate_repro} 4 | \alias{covid_estimate_repro} 5 | \title{Fit EpiEstim::estimate_R to covid19 data} 6 | \usage{ 7 | covid_estimate_repro( 8 | covid_data_prepared, 9 | estimate_method = "parametric_si", 10 | si_sample = NULL, 11 | config = list(mean_si = 4.7, std_si = 2.9) 12 | ) 13 | } 14 | \arguments{ 15 | \item{covid_data_prepared}{data is in the format provided by 16 | \code{covid_prepare_estimate_repro}, with columns "dates" and "I", where "dates" 17 | contains data of class "Date", and "I" contains cases.} 18 | 19 | \item{estimate_method}{default is "parametric_si"} 20 | 21 | \item{si_sample}{SI samples. Default is NULL.} 22 | 23 | \item{config}{named list of values to pass to EpiEstim::make_config. Default 24 | is \code{mean_si = 4.7}, and \code{std_si = 2.9}.} 25 | } 26 | \value{ 27 | estimated reproductive number 28 | } 29 | \description{ 30 | This fits EpiEstim::estimate_R, with config values \code{mean_si = 4.7} and 31 | \code{std_si = 2.9} from https://doi.org/10.1101/2020.02.03.20019497 32 | It assumes that the data is in the format provided by 33 | \code{covid_prepare_estimate_repro}. 34 | } 35 | -------------------------------------------------------------------------------- /R/global-vars.R: -------------------------------------------------------------------------------- 1 | if(getRversion() >= "2.15.1") utils::globalVariables(c(".")) 2 | globalVariables( 3 | c("alfa", 4 | "alfa2", 5 | "cases", 6 | "change_day", 7 | "change_point_date", 8 | "clabel_value", 9 | "clabel_x", 10 | "clabel_y", 11 | "countries_and_territories", 12 | "country_region", 13 | "covid", 14 | "cumulative_cases", 15 | "cumulative_deaths", 16 | "data", 17 | "date_rep", 18 | "date_since_limit_cases", 19 | "date_start_limit", 20 | "day", 21 | "days_to_double", 22 | "day_start_limit", 23 | "days_since_limit", 24 | "double_target", 25 | "deaths", 26 | "geo_id", 27 | "hit_100", 28 | "hit_limit", 29 | "incident_cases", 30 | "lag", 31 | "lag_cum_cases", 32 | "lead", 33 | "lead_date", 34 | "long", 35 | "mean_r", 36 | "median_r", 37 | "month", 38 | "min_date", 39 | "n_days", 40 | "n_double", 41 | "n_obs", 42 | "no_result", 43 | "normalised_date", 44 | "offset", 45 | "over_100", 46 | "over_limit", 47 | "pluck", 48 | "prepared_data", 49 | "province", 50 | "province_state", 51 | "quantile_0_025_r", 52 | "quantile_0_975_r", 53 | "repro_estimate", 54 | "repro_result", 55 | "result", 56 | "summarise", 57 | "week", 58 | "year") 59 | ) 60 | -------------------------------------------------------------------------------- /man/gg_covid_incidence_exceed_limit.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ggplot-helpers.R 3 | \name{gg_covid_incidence_exceed_limit} 4 | \alias{gg_covid_incidence_exceed_limit} 5 | \title{Base plot for creating incident cases chart of covid19 data} 6 | \usage{ 7 | gg_covid_incidence_exceed_limit( 8 | covid_data_limit, 9 | limit = NULL, 10 | highlight = "Australia", 11 | smooth = FALSE, 12 | span = 0.1 13 | ) 14 | } 15 | \arguments{ 16 | \item{covid_data_limit}{\itemize{ 17 | \item covid19 with added limit 18 | (from \code{\link[=add_days_since_limit]{add_days_since_limit()}}) 19 | }} 20 | 21 | \item{limit}{the number of days since reached a limit (added for 22 | titling graphic). Default is 100.} 23 | 24 | \item{highlight}{the name of the country to highlight, default is Australia.} 25 | 26 | \item{smooth}{add smoother, default is false} 27 | 28 | \item{span}{span numeric, span to add to smoother.} 29 | } 30 | \value{ 31 | ggplot plot 32 | } 33 | \description{ 34 | Base plot for creating incident cases chart of covid19 data 35 | } 36 | \examples{ 37 | \dontrun{ 38 | covid_data_since <- covid_data \%>\% 39 | add_days_since_limit(limit = 100) \%>\% 40 | dplyr::filter(days_since_limit >= 0) \%>\% 41 | dplyr::filter(country_region \%in\% c("Australia", "New Zealand")) 42 | 43 | gg_covid_cumulative_exceed_limit(covid_data_since) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /R/aa-utils.R: -------------------------------------------------------------------------------- 1 | str_remove_x <- function(x) stringr::str_remove_all(x, "x") 2 | 3 | covid_jhu_clean_date <- function(x) lubridate::mdy(str_remove_x(x)) 4 | 5 | add_continent <- function(x, country_source){ 6 | x %>% 7 | dplyr::mutate( 8 | continent = countrycode::countrycode( 9 | sourcevar = {{ country_source }}, 10 | origin = "country.name", 11 | destination = "continent", 12 | warn = FALSE 13 | ) 14 | ) 15 | } 16 | 17 | glue_date <- function(date){ 18 | glue::glue("https://www.ecdc.europa.eu/sites/default/files/documents/COVID-19-geographic-disbtribution-worldwide-{date}.xlsx") 19 | } 20 | 21 | discard_null <- function(x) purrr::discard(x, is.null) 22 | 23 | pluck_result <- function(x) purrr::pluck(x, "result") 24 | 25 | inherits_data_frames <- function(x) purrr::map_lgl(x, inherits, "data.frame") 26 | 27 | create_title_date <- function(covid_data){ 28 | date <- format(max(covid_data$date), "%d %B %Y") 29 | glue::glue("COVID-19 epidemic trajectories up to {date}") 30 | } 31 | 32 | 33 | #' Difference in days between two dates 34 | #' 35 | #' @param x first date 36 | #' @param y second date 37 | #' 38 | #' @return numeric number of days 39 | #' @export 40 | diff_days <- function(x, y){ 41 | as.numeric(difftime(x, y, units = "days")) 42 | } 43 | 44 | underscore_to_space <- function(x){ 45 | stringr::str_replace_all(string = x, 46 | pattern = "_", 47 | replacement = " ") 48 | } 49 | 50 | filter_last_country_date <- function(covid_data){ 51 | covid_data %>% 52 | dplyr::group_by(geo_id) %>% 53 | dplyr::filter(date == dplyr::last(date)) 54 | } 55 | -------------------------------------------------------------------------------- /R/observed-time-to-double.R: -------------------------------------------------------------------------------- 1 | #' Calculate the time to double covid19 data 2 | #' 3 | #' @param covid_data covid19 data 4 | #' 5 | #' @return data of country region, with `days_to_double`, and `double_target` 6 | #' being the "from x number of cases" 7 | #' 8 | #' @author Miles McBain 9 | #' 10 | #' @export 11 | covid_summarise_doubling <- function(covid_data) { 12 | 13 | country_cases <- 14 | covid_data %>% 15 | dplyr::filter(cases > 0) %>% 16 | dplyr::group_by(date, country_region) %>% 17 | dplyr::summarise(cases = sum(cases)) 18 | 19 | covid_double <- 20 | country_cases %>% 21 | dplyr::group_by(country_region) %>% 22 | dplyr::mutate(lead_date = lead(date), 23 | n_double = floor(log(cases, 2) - log(min(cases), 2))) %>% 24 | ## a = b * 2^n => log(a,2) - log(b,2) = n 25 | dplyr::group_by(country_region, n_double) %>% 26 | dplyr::mutate(days_to_double = as.numeric(max(lead_date) - min(date), 27 | units = "days")) %>% 28 | ## lead_date is the date of change 29 | dplyr::ungroup() %>% 30 | dplyr::group_by(country_region) %>% 31 | dplyr::mutate(double_target = min(cases) * 2^n_double) %>% 32 | dplyr::group_by(country_region, n_double) %>% 33 | dplyr::summarise( 34 | days_to_double = max(days_to_double), 35 | cases = min(cases), 36 | double_target = min(double_target) 37 | ) %>% 38 | tidyr::drop_na(days_to_double) %>% 39 | dplyr::ungroup() 40 | 41 | ## NAs occur in the final rows for each country, where we're still counting 42 | ## toward the next double. 43 | 44 | covid_double 45 | 46 | } 47 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export("%>%") 4 | export(add_country_hit_limit) 5 | export(add_country_label) 6 | export(add_country_row_id) 7 | export(add_covid_change_point) 8 | export(add_days_since_limit) 9 | export(add_instant_reproduction) 10 | export(add_weekly_avg) 11 | export(augment_estimate_repro) 12 | export(country_repro_errors) 13 | export(covid_change_point) 14 | export(covid_ecdc) 15 | export(covid_estimate_repro) 16 | export(covid_high_incidence) 17 | export(covid_highlight_australia_plus) 18 | export(covid_jhu) 19 | export(covid_jhu_clean_names) 20 | export(covid_jhu_filter_countres) 21 | export(covid_jhu_pivot_longer) 22 | export(covid_jhu_read) 23 | export(covid_latest) 24 | export(covid_prepare_estimate_repro) 25 | export(covid_summarise_doubling) 26 | export(diff_days) 27 | export(estimate_repro_all) 28 | export(extract_change_point_mean_var) 29 | export(extract_first_np_change_point) 30 | export(filter_country_over_limit) 31 | export(geom_covid_country_label) 32 | export(gg_covid_cases) 33 | export(gg_covid_cumulative_cases) 34 | export(gg_covid_cumulative_cases_deaths_exceed_limit) 35 | export(gg_covid_cumulative_exceed_limit) 36 | export(gg_covid_incidence_exceed_limit) 37 | export(gg_effective_repro_all) 38 | export(gg_effective_repro_facet) 39 | export(gg_effective_repro_incidence_patchwork) 40 | export(pluck_latest_ecdc) 41 | export(summarise_country_over_limit) 42 | export(summarise_covid_global) 43 | export(tidy_repro_estimate) 44 | export(try_ecdc) 45 | export(when_all_gt) 46 | export(when_all_gte) 47 | export(where_all_gt) 48 | export(where_all_gte) 49 | import(ggplot2) 50 | importFrom(magrittr,"%>%") 51 | -------------------------------------------------------------------------------- /vignettes/log_inc-log-cuminc-charts.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Log incidence cumulative incidence" 3 | author: "Tim Churches" 4 | date: "29/03/2020" 5 | output: rmarkdown::html_vignette 6 | vignette: > 7 | %\VignetteIndexEntry{Log incidence cumulative incidence} 8 | %\VignetteEngine{knitr::rmarkdown} 9 | %\VignetteEncoding{UTF-8} 10 | --- 11 | 12 | ```{r setup, include=FALSE} 13 | knitr::opts_chunk$set(echo = TRUE) 14 | ``` 15 | 16 | 17 | ```{r, fig.height=20, fig,width=12, meassage=FALSE} 18 | library(dplyr) 19 | library(tibble) 20 | library(ggplot2) 21 | library(lubridate) 22 | library(patchwork) 23 | library(EpiEstim) 24 | 25 | a <- tibble(R= (2.5 - (1:100)/50), 26 | I=round((1:100)^R), 27 | dates=ymd("2020-01-01") + days(1:100), 28 | cumI=cumsum(I), 29 | col = if_else(I == max(I), 1, 0)) 30 | 31 | estR <- estimate_R(select(a, dates, I), 32 | method="parametric_si", 33 | config = make_config(list( 34 | mean_si = 7.0, 35 | std_si = 3.0))) 36 | 37 | 38 | p0 <- ggplot(a, aes(x=cumI, y=I, col=col)) + geom_point() + 39 | scale_y_log10() + scale_x_log10() + 40 | labs(title="Log-log") 41 | 42 | p1 <- ggplot(a, aes(x=cumI, y=I, col=col)) + geom_point() + 43 | scale_y_continuous() + 44 | scale_x_continuous() + 45 | labs(title="Lin-Lin") 46 | 47 | 48 | p2 <- ggplot(a, aes(x=dates, y=I, col=col)) + geom_point() + 49 | labs(title="Linear incidence vs time") 50 | 51 | 52 | p3 <- ggplot(a, aes(x=dates, y=R, col=col)) + geom_point() + 53 | labs(title="Generating R vs time") 54 | 55 | 56 | p0 / p1 / p2 / p3 / plot(estR, "R") + scale_y_log10() 57 | 58 | ``` 59 | 60 | -------------------------------------------------------------------------------- /man/patch_data.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/patch-data.R 3 | \name{patch_data} 4 | \alias{patch_data} 5 | \title{Patch the case records for China and Italy} 6 | \usage{ 7 | patch_data(data) 8 | } 9 | \arguments{ 10 | \item{data}{data pulled by \code{try_ecdc} and \code{pluck_latest}.} 11 | } 12 | \value{ 13 | data.frame with adjusted cases 14 | } 15 | \description{ 16 | In Mid February 2020, China changed their case definition, from 17 | RT-PCR-swab-positive to test-positive or clinical signs of viral pneumonia. 18 | This led to a large spike not representative of cases. 19 | some further thoughts: 20 | \url{https://www.worldometers.info/coronavirus/how-to-interpret-feb-12-case-surge/} 21 | This changes the cases on the dates shown below to the verified lab-confirmed only counts 22 | available at 23 | https://en.wikipedia.org/w/index.php?title=Template:2019–20_coronavirus_pandemic_data/China_medical_cases_by_province&oldid=946973173 24 | Note that the EuroCDC data has dates a day later than the wikipedia data for China 25 | due to time zone differences. This adjustment is only valid for EuroCDC data, for the JHU 26 | data the dates for the adjustments need to be shifted back on day. 27 | - 13/2/2020 to 1820 cases (from 15141), 28 | - 14/2/2020 to 1995 cases (from 3237), 29 | - 15/2/2020 to 1503 cases (from 2538), 30 | - 16/2/2020 to 1121 cases (from 2007), 31 | } 32 | \details{ 33 | In addition, there are some anomalies with Italy, resulting in these changes\preformatted{- 15/3: to 3497 cases (from ...) 34 | - 16/3: to 3590 cases (from ...) 35 | - 17/3: to 3233 cases (from ...) 36 | } 37 | 38 | These changes for Italy came from the WHO situation reports: \url{https://www.who.int/emergencies/diseases/novel-coronavirus-2019/situation-reports}. 39 | } 40 | \note{ 41 | internal 42 | } 43 | -------------------------------------------------------------------------------- /R/cutting-room.R: -------------------------------------------------------------------------------- 1 | #' Add a country label for plotting 2 | #' 3 | #' This adds the appropriate lables for each country, to assist plotting 4 | #' with geom_label 5 | #' 6 | #' @param data covid19 data 7 | #' @param countries default adds all countries. Otherwise, they are 8 | #' specified with character vector. 9 | #' 10 | #' @return data.frame with added columns of selected countries 11 | #' @export 12 | add_country_label <- function(data, 13 | countries = unique(data$country_region)){ 14 | data %>% 15 | dplyr::mutate(clabel_value = dplyr::if_else( 16 | condition = country_region %in% countries, 17 | true = country_region, 18 | false = NA_character_ 19 | )) %>% 20 | dplyr::group_by(geo_id) %>% 21 | dplyr::arrange(geo_id, normalised_date) %>% 22 | dplyr::mutate(clabel_x = max(normalised_date), 23 | clabel_y = dplyr::last(cumulative_cases)) %>% 24 | dplyr::ungroup() 25 | } 26 | 27 | 28 | 29 | #' Adds nice country labels to ggplot, based on `add_country_label()` 30 | #' 31 | #' @return ggplot label added to ggplot 32 | #' @export 33 | geom_covid_country_label <- function(){ 34 | ggplot2::geom_label(ggplot2::aes(x = clabel_x, 35 | y = clabel_y, 36 | label = clabel_value), 37 | hjust = 0, 38 | nudge_x = 0.2) 39 | } 40 | 41 | 42 | #' Add alpha column which will highlight australia foremost, then ohters 43 | #' 44 | #' @param data covid19 data 45 | #' @param plus additional countries to highlight. Defaults to just Canada. 46 | #' 47 | #' @return data with added column "alpha" with extra info 48 | #' @export 49 | covid_highlight_australia_plus <- function(data, plus = "Canada"){ 50 | data %>% 51 | dplyr::mutate(alpha = dplyr::case_when( 52 | country_region == "Australia" ~ 1.0, 53 | country_region %in% plus ~ 0.2, 54 | TRUE ~ 0) 55 | ) 56 | } 57 | -------------------------------------------------------------------------------- /R/pull-covid-jhu.R: -------------------------------------------------------------------------------- 1 | #' read in raw covid19 data 2 | #' 3 | #' @return dataframe 4 | #' @export 5 | covid_jhu_read <- function(){ 6 | readr::read_csv("https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_19-covid-Confirmed.csv", 7 | col_types = readr::cols( 8 | .default = readr::col_double(), 9 | `Province/State` = readr::col_character(), 10 | `Country/Region` = readr::col_character() 11 | )) 12 | } 13 | 14 | #' clean variable names of covid19 raw data (from `covid_read`) 15 | #' 16 | #' @param x covid19 raw data 17 | #' 18 | #' @return data.frame with tidied names 19 | #' @export 20 | covid_jhu_clean_names <- function(x){ 21 | x %>% 22 | tibble::as_tibble(.name_repair = janitor::make_clean_names) %>% 23 | dplyr::rename(province = province_state) 24 | } 25 | 26 | #' pivots the covid19 data into longer form 27 | #' 28 | #' @param x data that has been imported and cleaned 29 | #' 30 | #' @return longer form pivoted data 31 | #' @export 32 | covid_jhu_pivot_longer <- function(x){ 33 | tidyr::pivot_longer(data = x, 34 | cols = -c(province:long), 35 | names_to = "date", 36 | values_to="cumulative_cases") 37 | } 38 | 39 | 40 | #' Pulls and tidies the latest covid19 data 41 | #' 42 | #' @return covid19 data with columns.. 43 | #' @export 44 | covid_jhu <- function(){ 45 | covid_jhu_read() %>% 46 | covid_jhu_clean_names() %>% 47 | covid_jhu_pivot_longer() %>% 48 | dplyr::mutate(date = covid_jhu_clean_date(date)) %>% 49 | dplyr::arrange(country_region, 50 | province, 51 | date) %>% 52 | dplyr::group_by(country_region, province) %>% 53 | dplyr::mutate(incident_cases = c(0, diff(cumulative_cases))) %>% 54 | dplyr::ungroup() %>% 55 | add_continent(country_source = country_region) 56 | 57 | } 58 | 59 | 60 | #' Filter covid countries to provided countries 61 | #' 62 | #' @param data covid19 data 63 | #' @param countries vector of countries 64 | #' 65 | #' @return dataset filtered to existing countries 66 | #' @export 67 | covid_jhu_filter_countres <- function(data, countries){ 68 | data %>% 69 | dplyr::filter(country_region %in% countries) 70 | } 71 | -------------------------------------------------------------------------------- /vignettes/cumulative-cases.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "COVID-19 trends and trajectories" 3 | author: 4 | - name: Tim Churches 5 | affiliation: South Western Sydney Clinical School, UNSW Medicine & Ingham Institute of Applied Medical Research, Liverpool, Sydney, Australia 6 | affiliation_url: https://swscs.med.unsw.edu.au 7 | - name: Nick Tierney 8 | affiliation: Monash University 9 | affiliation_url: 10 | date: 03-20-2020 11 | output: 12 | html_document: 13 | toc: true 14 | toc_depth: 3 15 | self_contained: true 16 | vignette: > 17 | %\VignetteIndexEntry{cumulative-cases} 18 | %\VignetteEngine{knitr::rmarkdown} 19 | %\VignetteEncoding{UTF-8} 20 | --- 21 | 22 | ```{r setup, include = FALSE} 23 | knitr::opts_chunk$set(echo = FALSE, 24 | cache = FALSE, 25 | collapse = TRUE, 26 | tidy.opts = list(width.cutoff = 60), 27 | tidy = TRUE) 28 | ``` 29 | 30 | ```{r libraries} 31 | library(covidrecon) 32 | library(dplyr) 33 | library(ggplot2) 34 | library(lubridate) 35 | library(ggplot2) 36 | library(ggrepel) 37 | ``` 38 | 39 | ```{r get-latest-data} 40 | covid <- covid_latest() 41 | ``` 42 | 43 | ```{r select-countries} 44 | selected_countries <- c("China", 45 | "Singapore", 46 | "Japan", 47 | "Italy", 48 | "Spain", 49 | "United_States_of_America", 50 | "United_Kingdom", 51 | "Australia", 52 | "South_Korea") 53 | 54 | ``` 55 | 56 | ```{r} 57 | covid_over_100 <- covid %>% 58 | filter_country_over_limit(limit = 100) 59 | ``` 60 | 61 | 62 | ```{r get-latest-data-highlight} 63 | gg_covid_cumulative_cases(covid_over_100) 64 | ``` 65 | 66 | ## The "Grattan Institute" cumulative incidence plot 67 | 68 | https://blog.grattan.edu.au/2020/03/australian-governments-can-choose-to-slow-the-spread-of-coronavirus-but-they-must-act-immediately/ 69 | 70 | ```{r since-100} 71 | covid_since_100 <- covid %>% 72 | add_days_since_limit(limit = 100) %>% 73 | filter(days_since_limit >= 0) 74 | ``` 75 | 76 | 77 | ```{r filter} 78 | covid_since_100_selected <- covid_since_100 %>% 79 | filter(country_region %in% selected_countries) 80 | covid_since_100_selected 81 | ``` 82 | 83 | ```{r} 84 | gg_covid_cumulative_exceed_limit(covid_since_100_selected) 85 | ``` 86 | 87 | -------------------------------------------------------------------------------- /R/patch-data.R: -------------------------------------------------------------------------------- 1 | #' Patch the case records for China and Italy 2 | #' 3 | #' In Mid February 2020, China changed their case definition, from 4 | #' RT-PCR-swab-positive to test-positive or clinical signs of viral pneumonia. 5 | #' This led to a large spike not representative of cases. 6 | #' some further thoughts: 7 | #' \url{https://www.worldometers.info/coronavirus/how-to-interpret-feb-12-case-surge/} 8 | #' This changes the cases on the dates shown below to the verified lab-confirmed only counts 9 | #' available at 10 | #' https://en.wikipedia.org/w/index.php?title=Template:2019–20_coronavirus_pandemic_data/China_medical_cases_by_province&oldid=946973173 11 | #' Note that the EuroCDC data has dates a day later than the wikipedia data for China 12 | #' due to time zone differences. This adjustment is only valid for EuroCDC data, for the JHU 13 | #' data the dates for the adjustments need to be shifted back on day. 14 | 15 | #' - 13/2/2020 to 1820 cases (from 15141), 16 | #' - 14/2/2020 to 1995 cases (from 3237), 17 | #' - 15/2/2020 to 1503 cases (from 2538), 18 | #' - 16/2/2020 to 1121 cases (from 2007), 19 | #' 20 | #' In addition, there are some anomalies with Italy, resulting in these changes 21 | #' 22 | #' - 15/3: to 3497 cases (from ...) 23 | #' - 16/3: to 3590 cases (from ...) 24 | #' - 17/3: to 3233 cases (from ...) 25 | #' 26 | #' These changes for Italy came from the WHO situation reports: \url{https://www.who.int/emergencies/diseases/novel-coronavirus-2019/situation-reports}. 27 | #' 28 | #' @param data data pulled by `try_ecdc` and `pluck_latest`. 29 | #' @note internal 30 | #' 31 | #' @return data.frame with adjusted cases 32 | patch_data <- function(data){ 33 | dplyr::mutate(data, 34 | cases = dplyr::case_when( 35 | geo_id == "CN" & year == 2020 & month == 2 & day == 13 ~ 1820, 36 | geo_id == "CN" & year == 2020 & month == 2 & day == 14 ~ 1995, 37 | geo_id == "CN" & year == 2020 & month == 2 & day == 15 ~ 1503, 38 | geo_id == "CN" & year == 2020 & month == 2 & day == 16 ~ 1121, 39 | # now for italy 40 | geo_id == "IT" & year == 2020 & month == 3 & day == 15 ~ 3497, 41 | geo_id == "IT" & year == 2020 & month == 3 & day == 16 ~ 3590, 42 | geo_id == "IT" & year == 2020 & month == 3 & day == 17 ~ 3233, 43 | TRUE ~ cases 44 | )) 45 | } 46 | -------------------------------------------------------------------------------- /vignettes/changepoint.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "changepoint" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{changepoint} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | ```{r, include = FALSE} 11 | knitr::opts_chunk$set( 12 | collapse = TRUE, 13 | comment = "#>" 14 | ) 15 | ``` 16 | 17 | ```{r setup} 18 | library(covidrecon) 19 | library(dplyr) 20 | library(ggplot2) 21 | ``` 22 | 23 | ```{r covid} 24 | covid <- covid_latest() 25 | covid_highest <- covid_high_incidence(covid) 26 | covid_changepoint <- add_covid_change_point(covid_highest) 27 | 28 | ``` 29 | 30 | ```{r highlight-countries} 31 | highlight_countries <- c("Japan", 32 | "South_Korea", 33 | "Singapore", 34 | "Italy", 35 | "Iran", 36 | "China", 37 | "France", 38 | "United_Kingdom", 39 | "Sweden", 40 | "Australia") 41 | 42 | ``` 43 | 44 | ```{r covid-highlight} 45 | covid_highlighted <- covid_changepoint %>% 46 | filter(country_region %in% c(highlight_countries, 47 | "United_States_of_America", 48 | "Germany", 49 | "Denmark")) 50 | ``` 51 | 52 | # Incident Cases 53 | 54 | ```{r covid-incident-cases, fig.width = 8, fig.height = 16} 55 | gg_covid_cases(covid_highlighted) + 56 | facet_grid(country_region ~ ., 57 | scales = "free_y") + 58 | geom_vline(aes(xintercept = change_point_date), 59 | colour = "salmon") 60 | ``` 61 | 62 | # Cumulative Cases 63 | 64 | ```{r covid-cumulative-cases, fig.width = 8, fig.height = 16} 65 | gg_covid_cumulative_cases(covid_highlighted) + 66 | facet_grid(country_region ~ ., 67 | scales = "free_y") + 68 | geom_vline(aes(xintercept = change_point_date), 69 | colour = "salmon") 70 | ``` 71 | 72 | # align countries along changepoint 73 | 74 | ```{r align-countries} 75 | covid_highlighted %>% 76 | group_by(country_region) %>% 77 | filter(date >= change_point_date) %>% 78 | mutate(days_since_change_point = diff_days(date, change_point_date)) %>% 79 | ggplot(aes(x = days_since_change_point, 80 | y = cumulative_cases, 81 | colour = country_region)) + 82 | geom_line() + 83 | scale_y_log10() 84 | ``` 85 | 86 | 87 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | 6 | 7 | ```{r setup, include = FALSE} 8 | knitr::opts_chunk$set( 9 | collapse = TRUE, 10 | comment = "#>", 11 | fig.path = "man/figures/README-", 12 | out.width = "100%" 13 | ) 14 | ``` 15 | 16 | # covidrecon 17 | 18 | 19 | [![DOI](https://zenodo.org/badge/248728805.svg)](https://zenodo.org/badge/latestdoi/248728805) 20 | 21 | 22 | R tools for monitoring effectiveness of COVID-19 control efforts 23 | 24 | ## Installation 25 | 26 | The development version from [GitHub](https://github.com/) with: 27 | 28 | ``` r 29 | # install.packages("devtools") 30 | devtools::install_github("CBDRH/covidrecon") 31 | ``` 32 | 33 | ## Why Another COVID19 R package? 34 | 35 | We created an [open source dashboard](https://cbdrh.github.io/ozcoviz/) to combine value-adding data visualisations with updated statistical analysis not yet widely seen. We decided to package up a lot of the code used in the dashboard into this R package. 36 | 37 | Now, there are many other R packages for pulling COVID19 data, so why create another one? A few reasons. The main one being that the COVID9 data formats, and other other R packages are changing rapidly. We wanted to perform statistical analysis that aren't widely available. We needed to ensure the data stayed in a format that was easily usable for our purposes. We needed something that we could control and add features to ourselves, that wouldn't need to rely on from another person. 38 | 39 | This package is still changing and evolving, and it's primary purpose is to implement code 40 | 41 | ## Usage 42 | 43 | `covidrecon` is designed to add statistical analysis and data visualisations of covid19 data. It was created to power [this dashboard](https://cbdrh.github.io/ozcoviz/). 44 | 45 | ### Pulling data 46 | 47 | The data source that we recommend using is from the European CDC. You can get this data with `covid_latest()`. This will by default cache the data downloaded for that day. Here is what the data looks like. 48 | 49 | ```{r covid-ecdc} 50 | library(covidrecon) 51 | covid <- covid_latest() 52 | covid 53 | ``` 54 | 55 | This contains new names for the data (from European CDC) 56 | 57 | - dateRep --> date_rep 58 | - countriesAndTerritories --> countries_and_territories 59 | - geoId --> geo_id 60 | - countryterritoryCode --> countryterritory_code 61 | - popData2018 --> pop_data2018 62 | 63 | 64 | For full use of the package and the data visualisations, we recommend that you look at the dashboard, [`ozcovis`](https://cbdrh.github.io/ozcoviz/). 65 | 66 | -------------------------------------------------------------------------------- /vignettes/instant-reproduction-num.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "instant-reproduction-num" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{instant-reproduction-num} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | ```{r, include = FALSE} 11 | knitr::opts_chunk$set( 12 | collapse = TRUE, 13 | comment = "#>" 14 | ) 15 | ``` 16 | 17 | ```{r setup} 18 | library(covidrecon) 19 | library(dplyr) 20 | library(ggplot2) 21 | library(tidyr) 22 | library(purrr) 23 | ``` 24 | 25 | ```{r} 26 | covid <- covid_latest() 27 | ``` 28 | 29 | ```{r highlight-countries} 30 | highlight_countries <- c("Japan", 31 | "South_Korea", 32 | "Singapore", 33 | "Italy", 34 | "Iran", 35 | "China", 36 | "France", 37 | "United_Kingdom", 38 | "Sweden", 39 | "Australia") 40 | 41 | ``` 42 | 43 | ```{r covid-highlight} 44 | covid_subset <- covid %>% 45 | filter(country_region %in% c(highlight_countries, 46 | "United_States_of_America", 47 | "Germany", 48 | "Denmark")) 49 | 50 | covid_changepoint <- covid_subset %>% 51 | add_covid_change_point() %>% 52 | filter(date >= change_point_date) 53 | ``` 54 | 55 | ## Instantaneous effective reproduction number 56 | 57 | ```{r} 58 | covid_instant_r <- add_instant_reproduction(covid_changepoint) 59 | ``` 60 | 61 | ```{r gg-effective-r, eval = TRUE, fig.height=8, fig.width=8, layout="l-page"} 62 | gg_effective_repro_facet(covid_instant_r) 63 | ``` 64 | 65 | ```{r, eval = FALSE, fig.height=8, fig.width=8, layout="l-page"} 66 | 67 | gg_effective_repro_all(covid_instant_r) 68 | 69 | ``` 70 | 71 | 72 | ```{r eval = FALSE} 73 | library(lubridate) 74 | 75 | gg + 76 | geom_line_interactive(size = 1.2) %>% 77 | girafe(ggobj = ., 78 | options = list( 79 | opts_tooltip(use_stroke = TRUE, opacity = 0.7), 80 | opts_hover(css = "stroke:black;"), 81 | opts_toolbar(position = "topright", saveaspng = TRUE) 82 | )) 83 | 84 | hubei_incidence_function_data <- covid %>% 85 | filter(date >= ymd("2020-01-11")) %>% 86 | mutate(HubeiSansWuhan = if_else( 87 | condition = is.na(HubeiSansWuhan), 88 | true = 0, 89 | false = HubeiSansWuhan)) %>% 90 | mutate(incident_cases = ifelse(Date < ymd("2020-02-15"), 91 | Wuhan + HubeiSansWuhan, Hubei)) %>% mutate(date = format(date, 92 | "%Y-%m-%d")) %>% 93 | select(Date, incident_cases) 94 | %>% uncount(incident_cases) 95 | hubei_incidence_object <- incidence(hubei_incidence_function_data$Date) 96 | ``` 97 | 98 | 99 | # exploring errors 100 | 101 | ```{r eval = FALSE} 102 | countries_errors <- country_repro_errors(covid_estimated_repro) 103 | 104 | covid_estimated_repro %>% 105 | filter(geo_id %in% countries_errors) %>% 106 | select(geo_id, 107 | repro_estimate) %>% 108 | unnest(cols = c(repro_estimate)) %>% 109 | slice(2) %>% 110 | pull(repro_estimate) 111 | ``` 112 | -------------------------------------------------------------------------------- /R/changepoint.R: -------------------------------------------------------------------------------- 1 | #' Extract changepoint 2 | #' 3 | #' @param data data.frame 4 | #' @param x variable name (as character) of cases. Default is "cases". 5 | #' @param ... params to pass to `changepoint::cpt.meanvar` 6 | #' 7 | #' @return changepoint vars 8 | #' @export 9 | extract_change_point_mean_var <- function(data, 10 | x = "cases", 11 | ...){ 12 | cpt_mean_var <- changepoint::cpt.meanvar(data[[x]], 13 | class = FALSE, 14 | ...) 15 | cpt_mean_var["cpt"] 16 | } 17 | 18 | #' Extract non-parametric changepoint 19 | #' 20 | #' @param data data.frame 21 | #' @param x variable name (as character) of cases. Default is "cases". 22 | #' @param ... params to pass to `changepoint.np::cpt.np` 23 | #' 24 | #' @return changepoint vars 25 | #' @export 26 | extract_first_np_change_point <- function(data, 27 | x = "cases", 28 | ...){ 29 | cpt_np <- changepoint.np::cpt.np(data[[x]], 30 | method="PELT", 31 | minseglen=5, 32 | nquantiles =4*log(length(data)), 33 | class = FALSE, 34 | ...) 35 | cpt_np[1] 36 | } 37 | 38 | #' Calculate changepoint date using `changepoint::cpt.meanvar` 39 | #' 40 | #' @param covid_data data.frame 41 | #' @param x variable name (as character) of cases. Default is "cases". 42 | #' @param ... params to pass to `changepoint::cpt.meanvar` 43 | #' 44 | #' @return data.frame of changepoints 45 | #' @export 46 | covid_change_point <- function(covid_data, 47 | x = "cases", 48 | ...){ 49 | 50 | covid_data <- covid_data %>% 51 | add_country_row_id() %>% 52 | dplyr::group_by(geo_id) %>% 53 | # dplyr::filter(cumulative_cases > 0) %>% 54 | dplyr::arrange(date) %>% 55 | dplyr::mutate(n_obs = vctrs::vec_size(geo_id)) %>% 56 | # remove countries with only 4 observations 57 | dplyr::filter(n_obs > 4) %>% 58 | # ungroup() %>% 59 | dplyr::group_by(geo_id) %>% 60 | tidyr::nest() %>% 61 | dplyr::mutate(change_day = purrr::map_dbl(data, 62 | extract_first_np_change_point, 63 | # was: extract_change_point_mean_var, 64 | x, 65 | ...)) %>% 66 | tidyr::unnest(cols = c(data)) %>% 67 | dplyr::select(-year, 68 | -month, 69 | -day, 70 | -n_obs) 71 | 72 | covid_data %>% 73 | dplyr::filter(n_days == change_day) %>% 74 | dplyr::rename(change_point_date = date) %>% 75 | dplyr::select(geo_id, 76 | change_point_date) %>% 77 | dplyr::ungroup() 78 | } 79 | 80 | #' Adds changepoint date based on `changepoint.np::cpt.np` 81 | #' 82 | #' @param covid_data data.frame 83 | #' @param x variable name (as character) of cases. Default is "cases". 84 | #' @param ... params to pass to `changepoint.np::cpt.np` 85 | #' 86 | #' @return ggplot2 plot 87 | #' @export 88 | add_covid_change_point <- function(covid_data, 89 | x = "cases", 90 | ...){ 91 | covid_data %>% 92 | covid_change_point(x, ...) %>% 93 | dplyr::left_join(covid_data, by = "geo_id") %>% 94 | # monkey-patch the NZ changepoint 95 | # dplyr::mutate(change_point_date = ifelse(country_region == "New_Zealand", lubridate::ymd("2020-03-18", tz="UTC"), change_point_date)) %>% 96 | dplyr::mutate( 97 | change_point_date = dplyr::if_else( 98 | condition = country_region == "New_Zealand", 99 | true = lubridate::ymd_hm("2020-03-18 00:00"), 100 | false = change_point_date 101 | ) 102 | ) %>% 103 | dplyr::mutate(days_since_changepoint = as.integer(difftime(date, 104 | change_point_date, 105 | units="days"))) 106 | } 107 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # covidrecon 5 | 6 | 7 | 8 | [![DOI](https://zenodo.org/badge/248728805.svg)](https://zenodo.org/badge/latestdoi/248728805) 9 | 10 | [![eRum2020::CovidR](https://badgen.net/https/runkit.io/erum2020-covidr/badge/branches/master/churches-tierney-ozcoviz-dashboard-covidrecon-package?cache=300)](https://milano-r.github.io/erum2020-covidr-contest/churches-tierney-ozcoviz-dashboard-covidrecon-package.html) 11 | 12 | 13 | 14 | R tools for monitoring effectiveness of COVID-19 control efforts 15 | 16 | See also https://github.com/CBDRH/ozcoviz 17 | 18 | ## Installation 19 | 20 | The development version from [GitHub](https://github.com/) with: 21 | 22 | ``` r 23 | # install.packages("devtools") 24 | devtools::install_github("CBDRH/covidrecon") 25 | ``` 26 | 27 | ## Why Another COVID19 R package? 28 | 29 | We created an [open source dashboard](https://cbdrh.github.io/ozcoviz/) 30 | to combine value-adding data visualisations with updated statistical 31 | analysis not yet widely seen. We decided to package up a lot of the code 32 | used in the dashboard into this R package. 33 | 34 | Now, there are many other R packages for pulling COVID19 data, so why 35 | create another one? A few reasons. The main one being that the COVID9 36 | data formats, and other other R packages are changing rapidly. We wanted 37 | to perform statistical analysis that aren’t widely available. We needed 38 | to ensure the data stayed in a format that was easily usable for our 39 | purposes. We needed something that we could control and add features to 40 | ourselves, that wouldn’t need to rely on from another person. 41 | 42 | This package is still changing and evolving, and it’s primary purpose is 43 | to implement code 44 | 45 | ## Usage 46 | 47 | `covidrecon` is designed to add statistical analysis and data 48 | visualisations of covid19 data. It was created to power [this 49 | dashboard](https://cbdrh.github.io/ozcoviz/). 50 | 51 | ### Pulling data 52 | 53 | The data source that we recommend using is from the European CDC. You 54 | can get this data with `covid_latest()`. This will by default cache the 55 | data downloaded for that day. Here is what the data looks like. 56 | 57 | ``` r 58 | library(covidrecon) 59 | covid <- covid_latest() 60 | #> New names: 61 | #> * dateRep -> date_rep 62 | #> * countriesAndTerritories -> countries_and_territories 63 | #> * geoId -> geo_id 64 | #> * countryterritoryCode -> countryterritory_code 65 | #> * popData2018 -> pop_data2018 66 | #> New names: 67 | #> * dateRep -> date_rep 68 | #> * countriesAndTerritories -> countries_and_territories 69 | #> * geoId -> geo_id 70 | #> * countryterritoryCode -> countryterritory_code 71 | #> * popData2018 -> pop_data2018 72 | #> covid data extracted from 2019-12-31 UTC to 2020-04-14 UTC 73 | covid 74 | #> # A tibble: 10,742 x 13 75 | #> date country_region deaths cases cumulative_cases 76 | #> 77 | #> 1 2020-03-03 00:00:00 Andorra 0 1 1 78 | #> 2 2020-03-14 00:00:00 Andorra 0 1 2 79 | #> 3 2020-03-16 00:00:00 Andorra 0 3 5 80 | #> 4 2020-03-17 00:00:00 Andorra 0 9 14 81 | #> 5 2020-03-18 00:00:00 Andorra 0 0 14 82 | #> 6 2020-03-19 00:00:00 Andorra 0 39 53 83 | #> 7 2020-03-20 00:00:00 Andorra 0 22 75 84 | #> 8 2020-03-21 00:00:00 Andorra 0 0 75 85 | #> 9 2020-03-22 00:00:00 Andorra 0 13 88 86 | #> 10 2020-03-23 00:00:00 Andorra 0 25 113 87 | #> # … with 10,732 more rows, and 8 more variables: cumulative_deaths , 88 | #> # year , month , week , day , geo_id , 89 | #> # countryterritory_code , pop_data2018 90 | ``` 91 | 92 | This contains new names for the data (from European CDC) 93 | 94 | - dateRep –\> date\_rep 95 | - countriesAndTerritories –\> countries\_and\_territories 96 | - geoId –\> geo\_id 97 | - countryterritoryCode –\> countryterritory\_code 98 | - popData2018 –\> pop\_data2018 99 | 100 | For full use of the package and the data visualisations, we recommend 101 | that you look at the dashboard, 102 | [`ozcovis`](https://cbdrh.github.io/ozcoviz/). 103 | -------------------------------------------------------------------------------- /R/country-over-limit.R: -------------------------------------------------------------------------------- 1 | #' Add a column that indicates when a country hits a limit of cases 2 | #' 3 | #' Requires that country is called `country_region`, date is called `date`, 4 | #' cumulative cases are called `cumulative_cases`. 5 | #' 6 | #' @param covid_data covid19 data with cumulative cases for each country 7 | #' @param limit defaults to 100 8 | #' 9 | #' @return data.frame with additional column "hit limit" indicating the day 10 | #' a country passed that limit 11 | #' @export 12 | #' 13 | #' @examples 14 | #' # covid %>% 15 | # # add_country_hit_limit() 16 | add_country_hit_limit <- function(covid_data, limit = 100){ 17 | covid_data %>% 18 | dplyr::arrange(geo_id, date) %>% 19 | dplyr::mutate( 20 | lag_cum_cases = lag(cumulative_cases), 21 | hit_limit = (cumulative_cases >= limit) & (lag_cum_cases < limit) 22 | ) %>% 23 | # hit_limit = ( 24 | # geo_id == "CN" & date == min(date) 25 | # ), 26 | # hit_limit = dplyr::if_else( 27 | # condition = 28 | # # geo_id != "CN" & 29 | # (cumulative_cases >= limit) & 30 | # (lag_cum_cases < limit), 31 | # true = TRUE, 32 | # false = hit_limit 33 | # ), 34 | # hit_limit = (cumulative_cases >= limit), 35 | # china was over the limit before data was collected (from before ) 36 | # hit_limit = dplyr::if_else( 37 | # condition = geo_id == "CN" & date == min(date), 38 | # true = TRUE, 39 | # false = FALSE 40 | # ) 41 | # ) %>% 42 | # we don't need this anymore 43 | dplyr::select(-lag_cum_cases) %>% 44 | dplyr::ungroup() 45 | } 46 | 47 | 48 | # possible refactor 49 | 50 | # 51 | # df_1 <- covid_over_limit %>% 52 | # filter(hit_limit) %>% 53 | # select(-hit_limit) 54 | # 55 | # df_2 <- covid %>% 56 | # group_by(country_region) %>% 57 | # slice(where_all_gte(cumulative_cases, 100)) %>% 58 | # ungroup() 59 | # 60 | # all.equal(names(df_1), names(df_2)) 61 | # all.equal(dim(df_1), dim(df_2)) 62 | # all.equal(df_1, df_2) 63 | # 64 | # visdat::vis_compare(df_1, df_2) 65 | # 66 | # df_1[14:19, ] 67 | # df_2[14:19, ] 68 | # 69 | # df_1 <- 70 | # covid %>% 71 | # group_by(country_region) %>% 72 | # mutate(hit_limit = ( 73 | # row_number() == where_all_gt(cumulative_cases, 100) 74 | # )) %>% 75 | # ungroup() 76 | # 77 | # df_2 <- covid_over_limit 78 | # 79 | # identical(df_1, df_2) 80 | # all.equal(df_1, df_2) 81 | 82 | 83 | #' Create a summary for each country, and a flag of whether they are over limit 84 | #' 85 | #' @param covid_data covid19 data 86 | #' @param limit limit 87 | #' 88 | #' @return data.frame with two columns, `country_region` and `over_limit` 89 | #' @export 90 | summarise_country_over_limit <- function(covid_data, limit = 100){ 91 | covid_data %>% 92 | add_country_hit_limit(limit = limit) %>% 93 | dplyr::group_by(geo_id) %>% 94 | dplyr::summarise(over_limit = any(hit_limit)) 95 | } 96 | 97 | #' Filter data to only include countries that have more than a certain number 98 | #' of cases 99 | #' 100 | #' @param covid_data covid19 data 101 | #' @param limit number of cases - default over 100 102 | #' 103 | #' @return data.frame with covid data that has more than 100 cases 104 | #' @export 105 | filter_country_over_limit <- function(covid_data, limit = 100){ 106 | dplyr::left_join( 107 | x = add_country_hit_limit(covid_data, limit = limit), 108 | y = summarise_country_over_limit(covid_data, limit = limit), 109 | by = "geo_id" 110 | ) %>% 111 | dplyr::filter(over_limit) 112 | } 113 | 114 | #' Add a column of the days since some limit of cumulative cases is reached 115 | #' 116 | #' @param covid_data covid19 data 117 | #' @param limit limit for flagging 118 | #' 119 | #' @return data.frame with extra column, "days_since_limit", which contains 120 | #' the number of days since the cumulative cases reached 100. 121 | #' @export 122 | add_days_since_limit <- function(covid_data, limit = 100) { 123 | # return a dataset that just contains the country and the date they started 124 | # reaching certain cumulative cases 125 | days_at_start <- covid_data %>% 126 | add_country_hit_limit(limit = limit) %>% 127 | dplyr::filter(hit_limit) %>% 128 | dplyr::select(geo_id, 129 | date_start_limit = date) 130 | 131 | dplyr::left_join(x = covid_data, 132 | y = days_at_start, 133 | by = "geo_id") %>% 134 | dplyr::arrange(geo_id, date) %>% 135 | dplyr::group_by(geo_id) %>% 136 | dplyr::mutate(days_since_limit = diff_days(date, date_start_limit)) %>% 137 | dplyr::ungroup() 138 | } 139 | -------------------------------------------------------------------------------- /R/pull-covid-cdc.R: -------------------------------------------------------------------------------- 1 | #' Download raw COVID19 data from European CDC 2 | #' 3 | #' This function will download raw COVID19 data, given a date. 4 | #' It will error if you enter a date that is later than the current date 5 | #' on the CDC site. See `latest_covid()` for a function that handles 6 | #' the full details of this. 7 | #' 8 | #' @param date in format "YYYY-MM-DD". So, "2020-01-01" is 1st Jan, 2020 9 | #' 10 | #' @return data.frame 11 | #' @export 12 | covid_ecdc <- function(date){ 13 | url <- glue_date(date) 14 | httr::GET(url = url, 15 | config = httr::authenticate(":", ":", type="ntlm"), 16 | httr::write_disk(tf <- tempfile(fileext = ".xlsx"))) 17 | 18 | readxl::read_excel(tf, .name_repair = janitor::make_clean_names) 19 | } 20 | 21 | #' Downloads both yesterday and today's COVID19 data 22 | #' 23 | #' Assuming CET time zones. For use within `latest_covid()`. 24 | #' 25 | #' @param memoise do you want to memoise (cache the data?). Default is TRUE 26 | #' 27 | #' @return list of yesterdays and today's COVID19 data 28 | #' @export 29 | try_ecdc <- function(memoise = TRUE){ 30 | 31 | todays_date <- format(lubridate::today(tz = "CET"), "%Y-%m-%d") 32 | yesterday <- format(lubridate::today(tz = "CET") - 1L, "%Y-%m-%d") 33 | 34 | # memoise covid19 data 35 | if (memoise) { 36 | covid_cache <- memoise::cache_filesystem(".covid_cache") 37 | memoise_covid <- memoise::memoise(covid_ecdc, cache = covid_cache) 38 | } 39 | 40 | safe_covid_ecdc <- purrr::safely(memoise_covid) 41 | purrr::flatten( 42 | list( 43 | today = discard_null(safe_covid_ecdc(todays_date)), 44 | yesterday = discard_null(safe_covid_ecdc(yesterday)) 45 | ) 46 | ) 47 | } 48 | 49 | #' Pull latest covid19 data from European CDC 50 | #' 51 | #' This pull data from \url{https://www.ecdc.europa.eu/en/publications-data/download-todays-data-geographic-distribution-covid-19-cases-worldwide}. 52 | #' 53 | #' @param patch logical. Patch China miscounts see [patch_data()]. 54 | #' Default is TRUE. 55 | #' @param memoise do you want to memoise (cache the data?). Default is TRUE. 56 | #' This caches the data into `.covid_cache` 57 | #' @param check_australia - do you want to check if Australia has been given 58 | #' zero cases for the latest day (since March 16), and if so, replace 59 | #' those recent days with NA? Default is TRUE 60 | #' 61 | #' @return data.frame 62 | #' @export 63 | covid_latest <- function(patch = TRUE, 64 | memoise = TRUE, 65 | check_australia = TRUE){ 66 | 67 | data <- try_ecdc(memoise) 68 | 69 | latest_data <- pluck_latest_ecdc(data) 70 | 71 | if (patch) { 72 | latest_data <- patch_data(latest_data) 73 | } 74 | 75 | tidy_covid <- latest_data %>% 76 | dplyr::rename(date = date_rep, 77 | country_region = countries_and_territories) %>% 78 | # dplyr::arrange(country_region, desc(date)) %>% 79 | dplyr::arrange(date) %>% 80 | dplyr::group_by(geo_id) %>% 81 | dplyr::mutate(cumulative_cases = cumsum(cases), 82 | cumulative_deaths = cumsum(deaths), 83 | week = lubridate::week(date)) %>% 84 | dplyr::ungroup() %>% 85 | dplyr::select(date, 86 | country_region, 87 | deaths, 88 | cases, 89 | cumulative_cases, 90 | cumulative_deaths, 91 | year, 92 | month, 93 | week, 94 | day, 95 | dplyr::everything()) %>% 96 | dplyr::arrange(geo_id, date) 97 | 98 | if (check_australia) { 99 | 100 | prop_date <- lubridate::dmy("16-03-2020") 101 | 102 | tidy_covid <- tidy_covid %>% 103 | dplyr::mutate( 104 | cases = dplyr::case_when( 105 | geo_id == "AU" & date > prop_date & cases == 0 ~ NA_real_, 106 | TRUE ~ cases 107 | ), 108 | cumulative_cases = dplyr::case_when( 109 | geo_id == "AU" & date > prop_date & cases == 0 ~ NA_real_, 110 | TRUE ~ cumulative_cases 111 | ) 112 | ) 113 | } 114 | 115 | return(tidy_covid) 116 | } 117 | 118 | #' Pluck the latest ecdc data 119 | #' 120 | #' For internal use within covid19 extraction data 121 | #' 122 | #' @param data covid19 list of latest data pulled from `try_ecdc`. 123 | #' 124 | #' @return single data.frame 125 | #' @note internal 126 | #' @export 127 | pluck_latest_ecdc <- function(data) { 128 | # if we have data for both, take the latest date 129 | if (all(inherits_data_frames(data))) { 130 | covid_latest_dates <- c(max(data[[1]]$date_rep), 131 | max(data[[2]]$date_rep)) 132 | 133 | which_is_latest <- which.max(covid_latest_dates) 134 | 135 | latest_data <- data[[which_is_latest]] 136 | 137 | # else, only the "result" has a data.frame 138 | } else { 139 | latest_data <- pluck_result(data) 140 | } 141 | 142 | message( 143 | "covid data extracted from ", 144 | min(latest_data$date_rep), 145 | " UTC", 146 | " to ", 147 | max(latest_data$date_rep), 148 | " UTC" 149 | ) 150 | 151 | return(latest_data) 152 | 153 | } 154 | -------------------------------------------------------------------------------- /R/estimate-instant-reproduction.R: -------------------------------------------------------------------------------- 1 | #' Prepare covid19 data for estimating instant repro number 2 | #' 3 | #' @param covid_data covid19 data 4 | #' 5 | #' @return dataframe with columns "dates" and "I", ready for 6 | #' `EpiEstim::estimate_R` 7 | #' @export 8 | covid_prepare_estimate_repro <- function(covid_data){ 9 | covid_data %>% 10 | dplyr::ungroup() %>% 11 | # EpiEstim::estimate_R requires a specific format of data 12 | dplyr::mutate(date = as.Date(date)) %>% 13 | dplyr::mutate(cases = if_else(cases < 0, 0, cases)) %>% 14 | dplyr::select(dates = date, 15 | I = cases) 16 | } 17 | 18 | #' Fit EpiEstim::estimate_R to covid19 data 19 | #' 20 | #' This fits EpiEstim::estimate_R, with config values `mean_si = 4.7` and 21 | #' `std_si = 2.9` from https://doi.org/10.1101/2020.02.03.20019497 22 | #' It assumes that the data is in the format provided by 23 | #' `covid_prepare_estimate_repro`. 24 | #' 25 | #' @param covid_data_prepared data is in the format provided by 26 | #' `covid_prepare_estimate_repro`, with columns "dates" and "I", where "dates" 27 | #' contains data of class "Date", and "I" contains cases. 28 | #' @param estimate_method default is "parametric_si" 29 | #' @param si_sample SI samples. Default is NULL. 30 | #' @param config named list of values to pass to EpiEstim::make_config. Default 31 | #' is `mean_si = 4.7`, and `std_si = 2.9`. 32 | #' 33 | #' @return estimated reproductive number 34 | #' @export 35 | covid_estimate_repro <- function(covid_data_prepared, 36 | estimate_method = "parametric_si", 37 | si_sample = NULL, 38 | config = list(mean_si = 4.7, 39 | std_si = 2.9)){ 40 | if (estimate_method == "parametric_si") { 41 | 42 | EpiEstim::estimate_R(covid_data_prepared, 43 | method = estimate_method, 44 | config = EpiEstim::make_config(config)) 45 | 46 | } else if (estimate_method == "si_from_sample") { 47 | 48 | EpiEstim::estimate_R(covid_data_prepared, 49 | method = estimate_method, 50 | si_sample = si_sample, 51 | config = EpiEstim::make_config(config)) 52 | 53 | } 54 | } 55 | 56 | #' Tidies up output from `EpiEstim::estimate_R` 57 | #' 58 | #' @param covid_estimated_reproduction output from `EpiEstim::estimate_R` 59 | #' 60 | #' @return returns columns on estiamted instantaneous reproduction, and quantiles, 61 | #' as well as dates. 62 | #' @export 63 | tidy_repro_estimate <- function(covid_estimated_reproduction){ 64 | 65 | df_reproduction <- covid_estimated_reproduction$R 66 | 67 | date_range <- 8:length(covid_estimated_reproduction$dates) 68 | 69 | df_reproduction$date <- covid_estimated_reproduction$dates[date_range] 70 | 71 | tibble::as_tibble(df_reproduction, 72 | .name_repair = janitor::make_clean_names) 73 | } 74 | 75 | #' Fits instant reproduction for each country 76 | #' 77 | #' @param covid_data covid19 data 78 | #' @param estimate_method default is "parametric_si" 79 | #' @param si_sample SI samples. Default is NULL. 80 | #' @param config named list of values to pass to EpiEstim::make_config. Default 81 | #' is `mean_si = 4.7`, and `std_si = 2.9`. 82 | #' @name covid-estimate-repro 83 | #' 84 | #' @return data.frame with several list columns containing various output of 85 | #' `EpiEstim::estimate_R`. 86 | #' 87 | #' @export 88 | estimate_repro_all <- function(covid_data, 89 | estimate_method = "parametric_si", 90 | si_sample = NULL, 91 | config = list(mean_si = 4.7, 92 | std_si = 2.9)) { 93 | covid_data %>% 94 | dplyr::group_by(geo_id) %>% 95 | tidyr::nest() %>% 96 | dplyr::mutate( 97 | prepared_data = purrr::map(data, covid_prepare_estimate_repro), 98 | repro_estimate = purrr::map(prepared_data, 99 | purrr::safely(covid_estimate_repro), 100 | estimate_method = estimate_method, 101 | si_sample = si_sample, 102 | config = EpiEstim::make_config(config)), 103 | repro_result = purrr::map(repro_estimate, 104 | purrr::pluck, 105 | "result"), 106 | result = purrr::map(repro_result, tidy_repro_estimate) 107 | ) 108 | } 109 | 110 | #' Tidies output of `estimate_repro_all` 111 | #' 112 | #' @param covid_data_estimated covid19 data estimated with `estimate_repro_all` 113 | #' 114 | #' @return data.frame 115 | #' @export 116 | augment_estimate_repro <- function(covid_data_estimated){ 117 | covid_data_estimated %>% 118 | dplyr::select(geo_id, 119 | result) %>% 120 | tidyr::unnest(cols = c(result)) %>% 121 | dplyr::select(geo_id, 122 | date, 123 | dplyr::everything()) %>% 124 | dplyr::ungroup() 125 | } 126 | 127 | #' Extract (any) errors from `estimate_repro_all` 128 | #' 129 | #' @param covid_data_estimated data from `estimate_repro_all` 130 | #' 131 | #' @return vector of error messages 132 | #' @export 133 | country_repro_errors <- function(covid_data_estimated){ 134 | covid_data_estimated %>% 135 | dplyr::select(geo_id, 136 | result) %>% 137 | dplyr::mutate(no_result = purrr::map_lgl(result, function(x) nrow(x) == 0)) %>% 138 | dplyr::filter(no_result) %>% 139 | dplyr::pull(geo_id) 140 | 141 | } 142 | 143 | 144 | #' Add instant reproduction number measures to provided covid19 data 145 | #' 146 | #' @param covid_data covid19 data 147 | #' @inheritParams covid-estimate-repro 148 | #' 149 | #' @return data.frame with covid19 columns plus output of `EpiEstim::estimate_R` 150 | #' and columns on estimated mean R values and quantiles etc. 151 | #' @export 152 | add_instant_reproduction <- function(covid_data, 153 | estimate_method = "parametric_si", 154 | si_sample = NULL, 155 | config = list(mean_si = 4.7, 156 | std_si = 2.9)) { 157 | 158 | tidy_instant <- covid_data %>% 159 | estimate_repro_all(estimate_method = estimate_method, 160 | si_sample = si_sample, 161 | config = EpiEstim::make_config(config)) %>% 162 | augment_estimate_repro() 163 | 164 | covid_data %>% 165 | dplyr::mutate(date = as.Date(date)) %>% 166 | dplyr::left_join(tidy_instant, 167 | by = c("geo_id", "date")) 168 | 169 | } 170 | -------------------------------------------------------------------------------- /R/ggplot-helpers.R: -------------------------------------------------------------------------------- 1 | #' misc-ggplot funs for covid19 2 | #' 3 | #' @param covid_data covid19 data 4 | #' 5 | #' @return ggplot image 6 | #' @export 7 | #' @rdname gg-covid 8 | gg_covid_cases <- function(covid_data){ 9 | ggplot(data = covid_data, 10 | aes(x = date, 11 | y = cases, 12 | group = country_region)) + 13 | geom_line() + 14 | scale_y_log10() + 15 | theme(panel.grid.minor = element_blank()) 16 | } 17 | 18 | #' @export 19 | #' @name gg-covid 20 | gg_covid_cumulative_cases <- function(covid_data){ 21 | ggplot(data = covid_data, 22 | aes(x = date, 23 | y = cumulative_cases, 24 | group = country_region)) + 25 | geom_line() + 26 | scale_y_log10() + 27 | theme(panel.grid.minor = element_blank()) 28 | } 29 | 30 | 31 | #' Plot effective reproduction number 32 | #' 33 | #' @param covid_effective_r covid19 data with estimated effective R 34 | #' @param highlight character vector of countries to highlight. Default, "Australia" 35 | #' 36 | #' @return ggplot2 plot 37 | #' @rdname effective-repro 38 | #' @export 39 | gg_effective_repro_all <- function(covid_effective_r, 40 | highlight = "Australia"){ 41 | 42 | covid_effective_r <- covid_effective_r %>% 43 | dplyr::mutate( 44 | alfa = dplyr::if_else( 45 | condition = country_region == highlight, 46 | true = 1.0, 47 | false = 0.5 48 | ), 49 | alfa2 = dplyr::if_else( 50 | condition = country_region == highlight, 51 | true = 1.0, 52 | false = 0.75 53 | ) 54 | ) 55 | 56 | last_country_eff_rs <- filter_last_country_date(covid_effective_r) 57 | 58 | last_date <- format(max(covid_effective_r$date), "%d %B %Y") 59 | 60 | covid_effective_r %>% 61 | ggplot(aes(x = date, 62 | y = median_r, 63 | colour = country_region)) + 64 | geom_line(aes(alpha=alfa), 65 | size = 1) + 66 | geom_point(data = last_country_eff_rs, 67 | size = 2, 68 | alpha = 0.75) + 69 | geom_hline(yintercept = 1.0, colour = "red") + 70 | ggrepel::geom_label_repel( 71 | data = last_country_eff_rs, 72 | aes(label = country_region, alpha = alfa2), 73 | segment.size = 0.3, 74 | hjust = 0, 75 | # direction = "x", 76 | nudge_x = 0.5, 77 | xlim = c( 78 | max(covid_effective_r$date) + lubridate::days(1), 79 | max(covid_effective_r$date) + lubridate::days(5) 80 | ) 81 | ) + 82 | scale_y_log10() + 83 | scale_x_date( 84 | date_breaks = "1 week", 85 | date_labels = "%d %b", 86 | expand = expansion(mult = c(0, 0.25)) 87 | ) + 88 | scale_alpha(range=c(0.4, 1.0)) + 89 | labs( 90 | title = expression(paste( 91 | "7-day sliding window of effective reproduction number ", R[t]) 92 | ), 93 | subtitle = expression(paste("Epidemic is in decay phase if ", R[t], " is under red line")), 94 | x = "End date of 7-day sliding window", 95 | y = expression(paste("Effective reproduction number ", R[t], " (log scale)")), 96 | caption = paste("Tim Churches (UNSW) & Nick Tierney (Monash) 97 | Data source: European CDC up to", last_date) 98 | ) + 99 | theme_minimal() + 100 | theme(legend.position = "none", 101 | panel.grid.minor = element_blank()) 102 | 103 | } 104 | 105 | #' @name effective-repro 106 | #' @export 107 | gg_effective_repro_facet <- function(covid_effective_r){ 108 | 109 | ggplot(covid_effective_r, 110 | aes(x = date, 111 | y = median_r, 112 | colour = country_region)) + 113 | geom_line(size = 1, 114 | alpha = 0.75) + 115 | geom_point(data = filter_last_country_date(covid_effective_r), 116 | size = 2, 117 | alpha = 0.75) + 118 | geom_hline(yintercept = 1.0, colour = "red") + 119 | facet_wrap( ~ country_region, ncol = 3) + 120 | scale_y_log10() + 121 | scale_x_date(date_breaks = "1 week", 122 | date_labels = "%d %b") + 123 | labs( 124 | title = expression(paste( 125 | "7-day sliding window of effective reproduction number ", R[t]) 126 | ), 127 | subtitle = expression(paste("Epidemic is in decay phase if ", R[t], " is under red line")), 128 | x = "End date of 7-day sliding window", 129 | y = expression(paste("Effective reproduction number ", R[t], " (log scale)")), 130 | caption = paste("Tim Churches (UNSW) & Nick Tierney (Monash) 131 | Data source: European CDC up to", format(max(covid_effective_r$date), "%d %B %Y")) 132 | ) + 133 | theme_minimal() + 134 | theme(legend.position = "none", 135 | panel.grid.minor = element_blank()) 136 | 137 | } 138 | 139 | #' Effective Reproductive pathwork 140 | #' 141 | #' @param covid_data covid19 data 142 | #' @param covid_effective_r covid19 data with effective repro added with 143 | #' `covid_estimate_repro()`. 144 | #' @param country country to display 145 | #' @export 146 | gg_effective_repro_incidence_patchwork <- function(covid_effective_r, 147 | covid_data, 148 | country){ 149 | first_date <- covid_effective_r %>% 150 | dplyr::filter(country_region == country) %>% 151 | dplyr::summarise( 152 | min_date = min(date) - lubridate::days(7) 153 | ) %>% 154 | dplyr::pull(min_date) 155 | 156 | title_text <- paste0(country, 157 | ": sliding window effective reproduction number") 158 | 159 | rplot <- covid_effective_r %>% 160 | dplyr::filter(country_region == country) %>% 161 | ggplot( 162 | aes(x = date, 163 | y = median_r, 164 | colour = country_region)) + 165 | geom_ribbon(aes(ymin = quantile_0_025_r, 166 | ymax = quantile_0_975_r), 167 | alpha=0.2) + 168 | geom_line(size = 1, 169 | alpha = 0.75) + 170 | geom_point(data = filter_last_country_date( 171 | covid_effective_r %>% 172 | dplyr::filter(country_region == country) 173 | ), 174 | size = 2, 175 | alpha = 0.75) + 176 | geom_hline(yintercept = 1.0, colour = "red") + 177 | scale_y_log10() + 178 | scale_x_date(date_breaks = "1 week", 179 | date_labels = "%d %b", 180 | limits=c(first_date, NA)) + 181 | labs( 182 | title = title_text, 183 | subtitle = expression(paste("Epidemic is in decay phase if ", R[t], " is under red line")), 184 | x = "End date of 7-day sliding window", 185 | y = expression(paste( R[t], " (log scale)")) 186 | ) + 187 | theme_minimal() + 188 | theme(legend.position = "none", 189 | panel.grid.minor = element_blank()) + 190 | theme(axis.text.x=element_text(angle=45, hjust=1)) 191 | 192 | 193 | tcountry <- country 194 | if (country == "South Korea") { 195 | country = "South_Korea" 196 | } 197 | 198 | iplot <- covid_data %>% 199 | dplyr::mutate(date = as.Date(date)) %>% 200 | dplyr::filter(country_region == country, 201 | date >= first_date) %>% 202 | ggplot( 203 | aes(x = date, 204 | y = cases, 205 | fill = country_region)) + 206 | geom_col(stat="identity", 207 | alpha = 0.75) + 208 | scale_x_date(date_breaks = "1 week", 209 | date_labels = "%d %b", 210 | limits=c(first_date, NA)) + 211 | # scale_y_log10() + 212 | labs( 213 | title = paste0(tcountry, ": COVID-19 incidence"), 214 | x = "Date", 215 | y = "Incident cases", 216 | # y = "Incident cases\n(log scale)", 217 | caption = paste("Tim Churches (UNSW) & Nick Tierney (Monash) 218 | Data source: European CDC up to", format(max(covid_effective_r$date), "%d %B %Y")) 219 | ) + 220 | theme_minimal() + 221 | theme(legend.position = "none", 222 | panel.grid.minor = element_blank()) + 223 | theme(axis.text.x=element_text(angle=45, hjust=1)) 224 | 225 | return( rplot / iplot ) 226 | 227 | } 228 | 229 | #' Base plot for creating cumulative cases of covid19 data 230 | #' 231 | #' @param covid_data_limit - covid19 with added limit 232 | #' (from [add_days_since_limit()]) 233 | #' @param limit the number of days since reached a limit (added for 234 | #' titling graphic). Default is 100. 235 | #' @param highlight the name of the country to highlight, default is Australia. 236 | #' 237 | #' @return ggplot plot 238 | #' @import ggplot2 239 | #' @export 240 | #' @examples 241 | #' \dontrun{ 242 | #' covid_data_since <- covid_data %>% 243 | #' add_days_since_limit(limit = 100) %>% 244 | #' dplyr::filter(days_since_limit >= 0) %>% 245 | #' dplyr::filter(country_region %in% c("Australia", "New Zealand")) 246 | #' 247 | #' gg_covid_cumulative_exceed_limit(covid_data_since) 248 | #' } 249 | gg_covid_cumulative_exceed_limit <- function(covid_data_limit, 250 | limit = NULL, 251 | highlight = "Australia"){ 252 | 253 | covid_data_last <- filter_last_country_date(covid_data_limit) 254 | 255 | if (!is.null(limit)) { 256 | x_axis_lab <- glue::glue("Days since cumulative cases exceeded {limit}") 257 | } else { 258 | x_axis_lab <- "Days since commencement of epidemic in each country" 259 | } 260 | 261 | covid_data_limit %>% 262 | dplyr::mutate( 263 | alfa = dplyr::if_else( 264 | condition = country_region == highlight, 265 | true = 1, 266 | false = 0.5 267 | ) 268 | ) %>% 269 | ggplot(aes(x = days_since_limit, 270 | y = cumulative_cases, 271 | colour = country_region)) + 272 | geom_line(aes(alpha=alfa), size = 1) + 273 | geom_point(data = covid_data_last, 274 | size = 2) + 275 | scale_y_log10(labels = scales::comma) + 276 | scale_x_continuous(expand = expansion(mult = c(0, 0.1))) + 277 | scale_alpha(range=c(0.3, 1)) + 278 | theme_minimal() + 279 | labs(y = "Cumulative cases (logarithmic scale)", 280 | x = x_axis_lab, 281 | title = create_title_date(covid_data_limit)) + 282 | ggrepel::geom_text_repel(data = covid_data_last, 283 | aes(label = underscore_to_space(country_region)), 284 | size = 4, 285 | nudge_x = 4, 286 | # direction = "x", 287 | segment.alpha = 0.2, 288 | segment.size = 0.2 289 | ) + 290 | theme(legend.position = "none") + 291 | labs(caption = 292 | "Tim Churches (UNSW) & Nick Tierney (Monash) 293 | Data source: European CDC" 294 | ) 295 | } 296 | 297 | #' Base plot for creating cumulative cases vs deaths of covid19 data 298 | #' 299 | #' @param covid_data_limit - covid19 with added limit 300 | #' (from [add_days_since_limit()]) 301 | #' @param limit the number of days since reached a limit (added for 302 | #' titling graphic). Default is 100. 303 | #' @param highlight the name of the country to highlight, default is Australia. 304 | #' 305 | #' @return ggplot plot 306 | #' @import ggplot2 307 | #' @export 308 | gg_covid_cumulative_cases_deaths_exceed_limit <- function(covid_data_limit, 309 | limit = NULL, 310 | highlight = "Australia"){ 311 | 312 | covid_data_last <- filter_last_country_date(covid_data_limit) 313 | 314 | if (!is.null(limit)) { 315 | x_axis_lab <- glue::glue("Days since cumulative cases exceeded {limit}") 316 | } else { 317 | x_axis_lab <- "Days since commencement of epidemic in each country" 318 | } 319 | 320 | covid_data_limit %>% 321 | dplyr::mutate( 322 | alfa = dplyr::if_else( 323 | condition = country_region == highlight, 324 | true = 1, 325 | false = 0.5 326 | ) 327 | ) %>% 328 | ggplot(aes(x = days_since_limit, 329 | y = cumulative_cases)) + 330 | geom_line(aes(colour=cumulative_deaths), size = 2) + 331 | geom_point(data = covid_data_last, 332 | aes(colour=cumulative_deaths), 333 | size = 3) + 334 | facet_wrap(country_region~.) + 335 | scale_y_log10(labels = scales::comma) + 336 | scale_x_continuous(expand = expansion(mult = c(0, 0.1))) + 337 | # scale_alpha(range=c(0.3, 1)) + 338 | theme_minimal() + 339 | labs(y = "Cumulative cases (logarithmic scale)", 340 | x = x_axis_lab, 341 | title = create_title_date(covid_data_limit)) + 342 | # geom_text(data = covid_data_last, 343 | # aes(label = underscore_to_space(country_region)), 344 | # size = 4) + 345 | theme(legend.position = "right") + 346 | labs(caption = 347 | "Tim Churches (UNSW) & Nick Tierney (Monash) 348 | Data source: European CDC" 349 | ) 350 | } 351 | 352 | #' Base plot for creating incident cases chart of covid19 data 353 | #' 354 | #' @param covid_data_limit - covid19 with added limit 355 | #' (from [add_days_since_limit()]) 356 | #' @param limit the number of days since reached a limit (added for 357 | #' titling graphic). Default is 100. 358 | #' @param highlight the name of the country to highlight, default is Australia. 359 | #' @param smooth add smoother, default is false 360 | #' @param span span numeric, span to add to smoother. 361 | #' 362 | #' @return ggplot plot 363 | #' @import ggplot2 364 | #' @export 365 | #' @examples 366 | #' \dontrun{ 367 | #' covid_data_since <- covid_data %>% 368 | #' add_days_since_limit(limit = 100) %>% 369 | #' dplyr::filter(days_since_limit >= 0) %>% 370 | #' dplyr::filter(country_region %in% c("Australia", "New Zealand")) 371 | #' 372 | #' gg_covid_cumulative_exceed_limit(covid_data_since) 373 | #' } 374 | gg_covid_incidence_exceed_limit <- function(covid_data_limit, 375 | limit = NULL, 376 | highlight = "Australia", 377 | smooth=FALSE, 378 | span=0.1){ 379 | 380 | if (!is.null(limit)) { 381 | x_axis_lab <- glue::glue("Days since daily incident cases exceeded {limit}") 382 | } else { 383 | x_axis_lab <- "Days since commencement of epidemic in each country" 384 | } 385 | 386 | if (TRUE) { # was if (smooth) 387 | covid_data_limit <- covid_data_limit %>% 388 | dplyr::mutate( 389 | cases = ifelse( 390 | test = cases == 0, 391 | yes = NA, 392 | no = cases 393 | ) 394 | ) %>% 395 | dplyr::group_by(country_region) %>% 396 | dplyr::filter(!(days_since_limit == max(days_since_limit) & is.na(cases))) 397 | } 398 | 399 | covid_data_last <- filter_last_country_date(covid_data_limit) 400 | 401 | p1 <- covid_data_limit %>% 402 | dplyr::mutate( 403 | alfa = dplyr::if_else( 404 | condition = country_region == highlight, 405 | true = 1, 406 | false = 0.5 407 | ) 408 | ) %>% 409 | ggplot(aes(x = days_since_limit, 410 | y = cases, 411 | colour = country_region)) 412 | 413 | if (!smooth) { 414 | p1 <- p1 + 415 | geom_line(aes(alpha=alfa), size = 1) + 416 | geom_point(data = covid_data_last, 417 | size = 2) 418 | y_label <- "Daily incident cases (logarithmic scale)" 419 | } else { 420 | p1 <- p1 + 421 | geom_smooth(aes(alpha=alfa), se=FALSE, size = 1, span=span) 422 | y_label <- "Smoothed daily incident cases (logarithmic scale)" 423 | } 424 | 425 | p1 <- p1 + 426 | scale_x_continuous(expand = expansion(mult = c(0, 0.1))) + 427 | scale_alpha(range=c(0.3, 1)) + 428 | theme_minimal() + 429 | labs(y = "Daily incident cases (logarithmic scale)", 430 | x = x_axis_lab, 431 | title = create_title_date(covid_data_limit)) 432 | 433 | if (!smooth) { 434 | p1 <- p1 + 435 | ggrepel::geom_text_repel(data = covid_data_last, 436 | aes(label = underscore_to_space(country_region)), 437 | size = 4, 438 | nudge_x = 4, 439 | # direction = "x", 440 | segment.alpha = 0.2, 441 | segment.size = 0.2 442 | ) 443 | } else { 444 | p1 <- p1 + 445 | ggrepel::geom_label_repel(data = covid_data_last, 446 | aes(label = underscore_to_space(country_region)), 447 | size = 4, 448 | nudge_x = 4 , 449 | # direction = "x", 450 | segment.alpha = 0.3, 451 | # segment.size = 0.2, 452 | # arrow = arrow(length = unit(0.02, "npc")) 453 | ) 454 | 455 | } 456 | 457 | p1 + 458 | theme(legend.position = "none") + 459 | labs(caption = 460 | "Tim Churches (UNSW) & Nick Tierney (Monash) 461 | Data source: European CDC" 462 | ) 463 | } 464 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | --------------------------------------------------------------------------------