From 06d73a8d3a224184ece41c2161e5e9a34f6d650b Mon Sep 17 00:00:00 2001 From: Max Unsted Date: Mon, 20 Nov 2017 22:10:34 +0000 Subject: [PATCH 1/2] various fixes to produce 2017 publication these are quick fixes and I have not been running unit tests as I haven't had time --- R/GVA_by_sector.R | 2 +- R/GVA_by_sub_sector.R | 80 +++++++++++++ R/combine_GVA_long.R | 32 +++-- R/extract_ABS_data.R | 3 + R/extract_GVA_data.R | 17 +-- R/extract_tourism_data.R | 2 + R/overlap_table.R | 53 +++++++++ R/year_sector_data_index.R | 227 ++++++++++++++++++++++++++++++++++++ R/year_sector_table2.R | 57 +++++++++ R/year_sector_table_index.R | 68 +++++++++++ data/sic_mappings.rda | Bin 0 -> 2458 bytes excel_tables.R | 57 +++++++++ 12 files changed, 575 insertions(+), 23 deletions(-) create mode 100644 R/GVA_by_sub_sector.R create mode 100644 R/overlap_table.R create mode 100644 R/year_sector_data_index.R create mode 100644 R/year_sector_table2.R create mode 100644 R/year_sector_table_index.R create mode 100644 data/sic_mappings.rda create mode 100644 excel_tables.R diff --git a/R/GVA_by_sector.R b/R/GVA_by_sector.R index 6a4042c..8386b23 100644 --- a/R/GVA_by_sector.R +++ b/R/GVA_by_sector.R @@ -40,7 +40,7 @@ GVA_by_sector <- function( GVA_by_sector <- dplyr::group_by(combine_GVA_long, year, sector) %>% summarise(GVA = sum(BB16_GVA)) %>% - #append total UK GVA + #append total UK GVA by year bind_rows( filter(GVA, SIC == "year_total") %>% mutate(sector = "UK") %>% diff --git a/R/GVA_by_sub_sector.R b/R/GVA_by_sub_sector.R new file mode 100644 index 0000000..89b30ea --- /dev/null +++ b/R/GVA_by_sub_sector.R @@ -0,0 +1,80 @@ +#' @title Calculate GVA by sector +#' +#' @description Combines datasets exracted from the underlying spreadsheet using +#' the \code{extract_XXX} functions. +#' +#' NOTE: THIS FUNCTION RELIES ON DATA WHICH ARE CLASSIFIED AS +#' OFFICIAL-SENSITIVE. THE OUTPUT OF THIS FUNCTION IS AGGREGATED, AND +#' PUBLICALLY AVAILABLE IN THE FINAL STATISTICAL RELEASE, HOWEVER CARE MUST BE +#' EXERCISED WHEN CREATING A PIPELINE INCLUDING THIS FUNCTION. IT IS HIGHLY +#' ADVISEABLE TO ENSURE THAT THE DATA WHICH ARE CREATED BY THE \code{extract_} +#' FUNCTIONS ARE NOT STORED IN A FOLDER WHICH IS A GITHUB REPOSITORY TO +#' MITIGATE AGAINST ACCIDENTAL COMMITTING OF OFFICIAL DATA TO GITHUB. TOOLS TO +#' FURTHER HELP MITIGATE THIS RISK ARE AVAILABLE AT +#' https://github.com/ukgovdatascience/dotfiles. +#' +#' @details The best way to understand what happens when you run this function +#' is to view the source code. +#' +#' +#' @param combine_GVA_long data output from \code{eesectors::combine_GVA_long()}. +#' @param GVA ABS data as extracted by \code{eesectors::extract_GVA_data()}. +#' +#' @export +#' +#' @import dplyr + + +GVA_by_sub_sector <- function( + combine_GVA_long = combine_GVA_long, + GVA = GVA, + sub_sector = NULL +) { + + check_class(combine_GVA_long) + check_class(GVA) + + GVA_by_sub_sector <- combine_GVA_long %>% + filter(sector == sub_sector) %>% + group_by(year, sub_sector_categories) %>% + summarise(GVA = sum(BB16_GVA)) %>% + ungroup() %>% + + #append total sector GVA by year + bind_rows( + combine_GVA_long %>% + filter(sector == sub_sector) %>% + group_by(year) %>% + summarise(GVA = sum(BB16_GVA)) %>% + mutate(sub_sector_categories = + paste0(toupper(substr(sub_sector, 1, 1)), + substr(sub_sector, 2, nchar(sub_sector)))) %>% + select(year, sub_sector_categories, GVA) + ) %>% + + #append total UK GVA by year + bind_rows( + filter(GVA, SIC == "year_total") %>% + mutate(sub_sector_categories = "UK") %>% + select(year, sub_sector_categories, GVA) + ) %>% + + #final clean up + filter(year %in% 2010:max(attr(combine_GVA_long, "years"))) %>% + mutate(GVA = round(GVA, 2), + sub_sector_categories = factor(sub_sector_categories), + year = as.integer(year)) %>% + select(sub_sector_categories, year, GVA) %>% + arrange(year, sub_sector_categories) + + #check "tbl_df" "tbl" "data.frame" is class(gva_by sub sector) + # structure( + # GVA_by_sector, + # class = c("GVA_by_sector", class(combine_GVA_long)[-1]) + # ) + + structure( + GVA_by_sub_sector, + years = sort(unique(GVA_by_sub_sector$year)), + class = c("GVA_by_sector", class(GVA_by_sub_sector))) +} diff --git a/R/combine_GVA_long.R b/R/combine_GVA_long.R index 7098040..a156f2a 100644 --- a/R/combine_GVA_long.R +++ b/R/combine_GVA_long.R @@ -34,34 +34,46 @@ combine_GVA_long <- function( ABS = NULL, GVA = NULL, SIC91 = NULL, - DCMS_sectors = eesectors::DCMS_sectors) { + DCMS_sectors = eesectors::sic_mappings) { check_class(ABS) check_class(GVA) check_class(SIC91) abs_year <- max(attr(ABS, "years")) - #Annual business survey, duplicate 2014 data for 2015 and - #then duplicate non SIC91 then add SIC 91 with sales data - ABS_2015 <- filter(ABS, year == abs_year) %>% - mutate(year = abs_year + 1) %>% - #this line makes no sense to me - we are just duplicated rows we already - #have so surely it is redundant?? - bind_rows(filter(ABS, !SIC %in% unique(SIC91$SIC))) %>% + # #Annual business survey, duplicate 2014 data for 2015 and + # #then duplicate non SIC91 then add SIC 91 with sales data + # ABS_2015 <- filter(ABS, year == abs_year) %>% + # mutate(year = abs_year + 1) %>% + # + # #this line makes no sense to me - we are just duplicated rows we already + # #have so surely it is redundant?? + # bind_rows(filter(ABS, !SIC %in% unique(SIC91$SIC))) %>% + # + # #simply appending SIC sales data which supplements the ABS for SIC 91 + # bind_rows(SIC91) + + ABS_2015 <- ABS %>% + filter(!SIC %in% unique(SIC91$SIC)) %>% #simply appending SIC sales data which supplements the ABS for SIC 91 bind_rows(SIC91) + ABS_2015 <- + bind_rows( + ABS_2015, + filter(ABS_2015, year == abs_year) %>% + mutate(year = abs_year + 1)) # keep cases from ABS which have integer SIC - which is just a higher level SIC - denom <- filter(ABS_2015, SIC %in% unique(eesectors::DCMS_sectors$SIC2)) %>% + denom <- filter(ABS_2015, SIC %in% unique(eesectors::sic_mappings$SIC2)) %>% select(year, ABS, SIC) %>% rename(ABS_2digit_GVA = ABS, SIC2 = SIC) #add ABS to DCMS sectors - GVA_sectors <- left_join(eesectors::DCMS_sectors, ABS_2015, by = c('SIC')) %>% + GVA_sectors <- left_join(eesectors::sic_mappings, ABS_2015, by = c('SIC')) %>% rename(ABS_ind_GVA = ABS) %>% #drop cases where SIC is not in that sector - should do when building DCMS_sectors filter(present == TRUE) %>% diff --git a/R/extract_ABS_data.R b/R/extract_ABS_data.R index 0b8cbee..d7e74a9 100644 --- a/R/extract_ABS_data.R +++ b/R/extract_ABS_data.R @@ -102,6 +102,9 @@ extract_ABS_data <- function( } else stop("Invalid format argument") + #remove duplicate SIC 92 + df <- df[-149, ] + #determine most recent year of data years <- suppressWarnings(as.numeric(colnames(df))) years <- min(years[!is.na(years)]):max(years[!is.na(years)]) diff --git a/R/extract_GVA_data.R b/R/extract_GVA_data.R index b255fc1..e52dfbe 100644 --- a/R/extract_GVA_data.R +++ b/R/extract_GVA_data.R @@ -61,6 +61,7 @@ extract_GVA_data <- function( col_types = rep("numeric",dend[2])) ) + # subset data to the table we want data2 <- data.frame(t(data[dstart[1]:dend[1], (dstart[2] + 1):dend[2]])) colnames(data2) <- unlist(data[dstart[1]:dend[1], dstart[2]]) @@ -71,9 +72,10 @@ extract_GVA_data <- function( SIC <- as.character(t(SIC[cnames, (dstart[2] + 1):dend[2]])) gva <- cbind(SIC, data2, stringsAsFactors = FALSE) + gva[1, 1] <- "year_total" gva <- gva %>% - filter(SIC %in% eesectors::DCMS_sectors$SIC2) + filter(SIC %in% eesectors::DCMS_sectors$SIC2 | SIC == "year_total") #determine most recent year of data @@ -83,8 +85,8 @@ extract_GVA_data <- function( #check for missing columns na_col_test(gva) - #check number of SIC codes in dataset - if (nrow(gva) != length(unique((eesectors::DCMS_sectors$SIC2)))) + #check number of SIC codes in dataset (+1 for year_total) + if (nrow(gva) != length(unique((eesectors::DCMS_sectors$SIC2))) + 1) stop( paste0( "GVA data has rows for ", @@ -99,15 +101,6 @@ extract_GVA_data <- function( mutate(year = as.integer(year)) %>% as.tbl() - # add total of SICs for each year - totals <- gva2 %>% - group_by(year) %>% - summarise(GVA = sum(GVA)) %>% - mutate(SIC = "year_total") %>% - select(SIC, year, GVA) - - gva2 <- rbind(gva2, totals) - #check columns names if( !identical( diff --git a/R/extract_tourism_data.R b/R/extract_tourism_data.R index b0099f6..9a39b7c 100644 --- a/R/extract_tourism_data.R +++ b/R/extract_tourism_data.R @@ -79,6 +79,8 @@ extract_tourism_data <- function( x <- x[mask,] + x <- x[, 1:5] + # Return the data to the console. message( diff --git a/R/overlap_table.R b/R/overlap_table.R new file mode 100644 index 0000000..090b999 --- /dev/null +++ b/R/overlap_table.R @@ -0,0 +1,53 @@ + +overlap_table <- function(df) { + +# function find GVA for a specific sector, for sic codes only used by that +# sector and then sic codes it shares with other sectors +mysum <- function(sector_para) { + + # extract the sic codes used by sector + temp <- + df %>% + filter(sector == sector_para) %>% + .$SIC %>% + unique() + + # for the above sic codes sum gva by sector + df %>% + filter(year == 2016) %>% + filter(SIC %in% temp) %>% + group_by(sector) %>% + filter(sector != "all_dcms") %>% + summarise(sum(BB16_GVA)) +} + +sec_column <- df %>% + select(sector) %>% + filter(sector != "all_dcms") %>% + distinct() %>% + arrange(sector) + +final <- sec_column + +for (x in sec_column$sector) { + #val_quo = enquo(x) + #print(val_quo) + final <- full_join( + final, rename(mysum(x), x = `sum(BB16_GVA)`), by = c("sector")) +} + +names(final) <- c("sector", sec_column$sector) +mutate_all(final, function(x) ifelse(is.na(x),0,x)) + +} + +# to interpret output - for each row, the diagonal is the total GVA and each +# other columns are a subset set of this and give the amount the total needs +# to overlap lap with that sector + + + + + + + diff --git a/R/year_sector_data_index.R b/R/year_sector_data_index.R new file mode 100644 index 0000000..7a335f5 --- /dev/null +++ b/R/year_sector_data_index.R @@ -0,0 +1,227 @@ +#' @title long data class +#' +#' @description \code{year_sector_data} is the class used for the creation of tables +#' 3.1, 4.1, 4.5, and 5.1 of the DCMS Sectors Economic Estimate +#' (\url{https://www.gov.uk/government/uploads/system/uploads/attachment_data/file/544103/DCMS_Sectors_Economic_Estimates_-_August_2016.pdf}). +#' +#' +#' +#' @details The \code{year_sector_data} class expects a \code{data.frame} with three +#' columns: sector, year, and measure, where measure is one of GVA, exports, +#' or enterprises. The \code{data.frame} should include historical data, which +#' is used for checks on the quality of this year\'s data, and for producing +#' tables and plots. +#' +#' Once inititated, the class has five slots: \code{df}: the basic +#' \code{data.frame}, \code{colnames}: a character vector containing the +#' column names from the \code{df}, \code{type}: a character vector of +#' \code{length(type) == 1} describing the type of data (\"GVA\", \"exports\", +#' or \"enterprises\") imputed from column names, \code{sector_levels}: a +#' factor vector containing levels of \code{df$sector} of the factor sector, +#' \code{years}: an integer vector containing \code{unique(df$year)}. +#' +#' @param x Input dataframe, see details. +#' @param log_level The severity level at which log messages are written from +#' least to most serious: TRACE, DEBUG, INFO, WARN, ERROR, FATAL. Default is +#' level is INFO. See \code{?flog.threshold()} for additional details. +#' @param log_appender Defaults to write the log to "console", alternatively you +#' can provide a character string to specify a filename to also write to. See +#' for additional details \code{?futile.logger::appender.tee()}. +#' @param log_issues should issues with the data quality be logged to github? +#' See \code{?raise_issue()} for additional details. +#' +#' @return If the class is instantiated correctly, nothing is returned. +#' +#' @examples +#' +#' library(eesectors) +#' +#' GVA <- year_sector_data(GVA_by_sector_2016) +#' +#' @export + + +year_sector_data_index <- function(x, log_level = futile.logger::WARN, + log_appender = "console", + log_issues = FALSE) { + + # Set logger severity threshold, defaults to + # high level use (only flags warnings and errors) + # Set log_level argument to futile.logger::TRACE for full info + futile.logger::flog.threshold(log_level) + + # Set where to write the log to + if (log_appender != "console") + { + # if not console then to a file called... + futile.logger::flog.appender(futile.logger::appender.file(log_appender)) + } + + # Checks + futile.logger::flog.info('Initiating year_sector_data class. +\n\nExpects a data.frame with three columns: sector, year, and measure, where +measure is one of GVA, exports, or enterprises. The data.frame should include +historical data, which is used for checks on the quality of this year\'s data, +and for producing tables and plots. More information on the format expected by +this class is given by ?year_sector_data().') + + # Integrity checks on incoming data ---- + + # Check the structure of the data is as expected: data.frame containing no + # missing values and three columns, containing sector, year, and one + # additional column. + + futile.logger::flog.info('\n*** Running integrity checks on input dataframe (x):') + futile.logger::flog.debug('\nChecking input is properly formatted...') + + futile.logger::flog.debug('Checking x is a data.frame...') + if (!is.data.frame(x)) + { + futile.logger::flog.error("x must be a data.frame", + x, capture = TRUE) + } + + futile.logger::flog.debug('Checking x has correct columns...') + if (length(colnames(x)) != 3) + { + futile.logger::flog.error("x must have three columns: sector, year, and one of GVA, export, or x") + } + + futile.logger::flog.debug('Checking x contains a year column...') + if (!'year' %in% colnames(x)) stop("x must contain year column") + + futile.logger::flog.debug('Checking x contains a sector column...') + if (!'sector' %in% colnames(x)) stop("x must contain sector column") + + futile.logger::flog.debug('Checking x does not contain missing values...') + if (anyNA(x)) stop("x cannot contain any missing values") + + futile.logger::flog.debug('Checking for the correct number of rows...') + if (nrow(x) != length(unique(x$sector)) * length(unique(x$year))) { + futile.logger::flog.warn("x does not appear to be well formed. nrow(x) should equal + length(unique(x$sector)) * length(unique(x$year)). Check the of x.") + } + + + + futile.logger::flog.info('...passed') + + # User assertr to run statistical tests on the data itself ---- + + futile.logger::flog.info("\n***Running statistical checks on input dataframe (x)") + + futile.logger::flog.trace("These tests are implemented using the package assertr see: + https://cran.r-project.org/web/packages/assertr for more details.") + + # Extract third column name + + value <- colnames(x)[(!colnames(x) %in% c('sector','year'))] + + # Check snsible range for year + + futile.logger::flog.debug('Checking years in a sensible range (2000:2020)...') + + assertr::assert_(x, assertr::in_set(2000:2020), ~year) + + # Check that the correct levels are in sector + + futile.logger::flog.debug('Checking sectors are correct...') + + # Save sectors name lookup for use later + + sectors_set <- c( + "creative" = "Creative Industries", + "culture" = "Cultural Sector", + "digital" = "Digital Sector", + "gambling" = "Gambling", + "sport" = "Sport", + "telecoms" = "Telecoms", + "tourism" = "Tourism", + "all_dcms" = "All DCMS sectors", + "perc_of_UK" = "% of UK GVA", + "UK" = "UK" + ) + + assertr::assert_(x, assertr::in_set(names(sectors_set)), ~sector, error_fun = raise_issue) + + # Check for outliers ---- + + # Check for simple outliers in the value column (GVA, exports, enterprises) + # for each sector, over the entire timeseries. Outliers are detected using + # median +- 3 * median absolute deviation, implemented in the + # assertr::within_n_mads() function. + + futile.logger::flog.debug('Checking for outliers (x_i > median(x) + 3 * mad(x)) in each sector timeseries...') + + # Create a list split by series containing a df in each + + series_split <- split(x, x$sector) + + # Apply to each df in the list + + lapply( + X = series_split, + FUN = function(x) { + futile.logger::flog.trace("Checking sector timeseries: %s", + as.character(unique(x[['sector']])), + capture = FALSE) + assertr::insist_( + x, + assertr::within_n_mads(3), + lazyeval::interp(~value, value = as.name(value)), + error_fun = raise_issue) + } + ) + + futile.logger::flog.info('...passed') + + # Check for outliers using mahalanobis ---- + + # This test also looks for outliers, by considering the relationship between + # the variable year and the value variable. It measures the mahalabois + # distance, which is similar to the euclidean norm, and then looks for + # ourliers in this new vector of norms. Any value with a distance too great is + # flagged as an outlier. + + futile.logger::flog.debug('Checking for outliers on a row by row basis using mahalanobis distance...') + + lapply( + X = series_split, + FUN = maha_check + ) + + futile.logger::flog.debug('...passed') + + ### ISSUE - these might be "changing the world" for the user unexpectedly! + + # Reset threshold to package default + futile.logger::flog.threshold(futile.logger::INFO) + # Reset so that log is appended to console (the package default) + futile.logger::flog.appender(futile.logger::appender.console()) + + # Message required to pass a test + message("Checks completed successfully: +object of 'year_sector_data' class produced!") + + # add index for value column + x <- x %>% + # replaces values in sector with lookup in year_sector_data + mutate(sector = factor(unname(sectors_set[as.character(sector)]))) %>% + + # calculate the index (index_year=100) variable + group_by(sector) %>% + mutate(indexGVA = GVA/max(ifelse(year == min(x$year), GVA, 0)) * 100) + + # Define the class here ---- + + structure( + list( + df = x, + colnames = colnames(x), + type = colnames(x)[!colnames(x) %in% c('year','sector')], + sector_levels = levels(x$sector), + sectors_set = sectors_set, + years = unique(x$year) + ), + class = "year_sector_data_index") +} diff --git a/R/year_sector_table2.R b/R/year_sector_table2.R new file mode 100644 index 0000000..5b5eea0 --- /dev/null +++ b/R/year_sector_table2.R @@ -0,0 +1,57 @@ +#' @title year_sector_table() +#' +#' @description Generic method to convert tables into wide format +#' +#' @details Generic method to convert tables into wide format +#' +#' @param x Object of \code{class(x) == 'year_sector_data'}. +#' @param html Should the output be an R \code{data.frame} (and \code{tbl} and +#' \code{tbl_df}) or as html using \code{xtable}. +#' @param fmt Format for values in the table to be displayed as, following +#' \code{sprintf}. +#' @param ... Passes arguments to \code{print.xtable} and \code{xtable}. Will +#' silently be dropped if \code{html = FALSE}. +#' +#' @seealso \code{\link{sprintf}} +#' +#' @return wide format table +#' +#' @export + +# Define as a method +year_sector_table2 <- function(GVA_by_sub_sector, html, fmt, ...) { + + max_year <- max(attr(GVA_by_sub_sector, "year")) + measure <- "GVA" + + total2016 <- + GVA_by_sub_sector[ + GVA_by_sub_sector$sub_sector_categories == "UK" & + GVA_by_sub_sector$year == 2016,]$GVA + + df <- GVA_by_sub_sector %>% + #mutate(sector = factor(unname(sectors_set[as.character(sector)]))) %>% + + # calculate the index (index_year=100) variable + group_by(sub_sector_categories) %>% + tidyr::spread(key = year, value = GVA) %>% + mutate(change1516 = (`2016` / `2015` - 1) *100) %>% + mutate(change1015 = (`2016` / `2010` - 1) *100) %>% + mutate(ukperc = 100 * `2016` / total2016) %>% + + mutate_all(function(x) round(x, 1)) %>% + mutate(`2010` = round(`2010`, 0)) %>% + mutate(`2011` = round(`2011`, 0)) %>% + mutate(`2012` = round(`2012`, 0)) %>% + mutate(`2013` = round(`2013`, 0)) %>% + mutate(`2014` = round(`2014`, 0)) %>% + mutate(`2015` = round(`2015`, 0)) %>% + mutate(`2016` = round(`2016`, 0)) %>% + rename( + `Sub-sector` = sub_sector_categories, + `% change 2015 - 2016` = change1516, + `% change 2010 - 2016` = change1015, + `% of UK GVA 2016` = ukperc + ) + +} diff --git a/R/year_sector_table_index.R b/R/year_sector_table_index.R new file mode 100644 index 0000000..950800d --- /dev/null +++ b/R/year_sector_table_index.R @@ -0,0 +1,68 @@ +#' @title year_sector_table() +#' +#' @description Generic method to convert tables into wide format +#' +#' @details Generic method to convert tables into wide format +#' +#' @param x Object of \code{class(x) == 'year_sector_data'}. +#' @param html Should the output be an R \code{data.frame} (and \code{tbl} and +#' \code{tbl_df}) or as html using \code{xtable}. +#' @param fmt Format for values in the table to be displayed as, following +#' \code{sprintf}. +#' @param ... Passes arguments to \code{print.xtable} and \code{xtable}. Will +#' silently be dropped if \code{html = FALSE}. +#' +#' @seealso \code{\link{sprintf}} +#' +#' @return wide format table +#' +#' @export + +# Define as a method +year_sector_table_index <- function(x, html = FALSE, fmt = '%.1f', ...) { + + sectors_set <- c( + "creative" = "Creative Industries", + "culture" = "Cultural Sector", + "digital" = "Digital Sector", + "gambling" = "Gambling", + "sport" = "Sport", + "telecoms" = "Telecoms", + "tourism" = "Tourism", + "all_dcms" = "All DCMS sectors", + "perc_of_UK" = "% of UK GVA", + "UK" = "UK" + ) + + max_year <- max(x$year) + measure <- x$type + + # Extract stats for the whole of the UK ---- + + #data.frame(col1 = 1:4, col2 = 3:6) %>% rbind(1:2) + + df <- x$df %>% + mutate(sector = factor(unname(sectors_set[as.character(sector)]))) %>% + + # calculate the index (index_year=100) variable + group_by(sector) %>% + mutate(indexGVA = GVA/max(ifelse(year == min(x$year), GVA, 0)) * 100) %>% + + select(-GVA) %>% + tidyr::spread(key = year, value = indexGVA) %>% + mutate(change = (`2016` / `2015` - 1) *100) %>% + mutate_all(function(x) round(x, 1)) %>% + + mutate(`2010` = round(`2010`, 0)) %>% + mutate(`2011` = round(`2011`, 0)) %>% + mutate(`2012` = round(`2012`, 0)) %>% + mutate(`2013` = round(`2013`, 0)) %>% + mutate(`2014` = round(`2014`, 0)) %>% + mutate(`2015` = round(`2015`, 0)) %>% + mutate(`2016` = round(`2016`, 0)) %>% + + rename(Sector = sector, `% change 2015 - 2016` = change) + + df[nrow(df)+1,] <- NA + df <- df[c(2:8, 1, 10, 9),] +} diff --git a/data/sic_mappings.rda b/data/sic_mappings.rda new file mode 100644 index 0000000000000000000000000000000000000000..76a65cdd28ad86b9b19f9ebf5b9fae5261b4fc00 GIT binary patch literal 2458 zcmdUic{tM#1HkpGSGj*8Drb(CAGH`dTxo=gL=rYv6C0zMBS-usqE)WRbSPSr`6bIn!dAqaCDKm}Ac0^Ssad-}^l8|L^DXJfG+JXyNuq{2NID9F1ks6iNDCNlp;V zGh!UpT`xvZAFw|MZ-*g4fUqo$OTal@az))G&^e zd>I7 z%se$Pi}dxV`j|PFYfcO_R1|01Ar6CS#jf38J+)jpMmhre{?JHvn4|gsT4B=r{A6}a zL~6r;CZxkLvV#Sw|NPlCzUsK#5H_)o8@`{|tU$Yk&hi=?w3pP(yGmngUiVxp$^O*l zUlp_plTPl`C(CX1Ij+jf;icJcrB5rC1sDGwlV15QU8iOzU+@H8XsH z`&cHF$FY0?LYb_1fYuNlxKz68ytnzo+W{Ex%8!;kQ@%5D`dIZU@2d!!&c4*5zVc5p z?Lv@2;^|jsagU+*ZLho)_WQ_k_(6Zq822c!5r<-$xGf=7?qMWsf~#o_do-q zi29>!6Q2>b8lPIYKgZ~diM{~tdVo)kMm`ED^Ozo*^Pbth^?j6I1K&NboL}udo<1r@ zTKX;gZKz#yH#Pwt@+Far4Ra+D%>QTbwV%P6$u-SK{@FfX$-*u_D(pAM$81t|+Ke_1QA&4=c1B^1Tl9BNARV^VcNcowu*k2+TPgMMYu2~>Q%I$FC2 zDv0{+!DuR@-A``42EO{vA0i0J-c5H`Y(yzkeoT7OBCAwbE@aqteagUtnrynF6Bmr# zY9nZU=YIlcwp5N$6LlOcRJNjfE-==i&Q@_*+=zm|?=mWNa{f3S%8A*eatJxD&*w9C zaIrtT9lvFktiIDz4}c)wFy-bC8p-P8g7eE@BRUZB5%MXSLC7vIe0uY!F8(ic0A%-m zR@u%xRm5Me#6a50#AQ_e;IE3yczPsIt}CB@5q(1m1KN_BS;fmj!OP48e%pIkR8E^+ zVYZLW!jaF@#E|?uD>JyWjsnx#)7Izo&Q@HSnk=5{Bz;IWYtVA*UA^Zf>wsd}{6>WL zQZ!C~%xv2cCh>pa>UNqOw{`rc)%+*x-Es#_r-@87(ct!?Xz zT8Ljm!z2!xhV+A8-G_8!4>aKFQ1AF zX23EY=*0tbQGjo_Em-Rn6F?rlgaQBrur-JWVw?@@T3X%E$k35b2~9(k(NHCdGDPTc zqoyB@8Wu4r(n8%EisTHhPNP5-V;sT0N9Vs+nAme;e8~LZ33k8PlGVUXK{X;Fz+Zjf zHWu5=89-Wzd14pxo60MmR}T{k7q{F4ES#_N`88iJ4`pNQi|cD0eC@cu+cC-1Vw8{R zg?%1Vr&Uw_s(iW6GtT1NMOA~+CVx8aYu|@jl8aP#q(mCIj556J1=UgLS0HTT=i zkQ<)npdwfV8yIOd21E?AdAjA6J)%s584`792PJ6oQy_Ljq zs*Sowe?(+iOJP^DiZ?hWe!I4zuoQMJD04(Y;vZ8U)8YUC literal 0 HcmV?d00001 diff --git a/excel_tables.R b/excel_tables.R new file mode 100644 index 0000000..439231e --- /dev/null +++ b/excel_tables.R @@ -0,0 +1,57 @@ +#write.xlsx(year_sector_table(combined_GVA), file = "hellomax.xlsx") +#install.packages("openxlsx") +library(openxlsx) + +wb <- loadWorkbook(file = + "G:/Economic Estimates/Rmarkdown/DCMS_Sectors_Economic_Estimates_Template.xlsx") + +ysd_headings <- + c("sector", + GVA_by_sector2$years, + "% change 2015 - 2016", + "% change 2010-2016", + "% of UK GVA 2016") %>% + matrix(nrow = 1) + +# Contents +writeData(wb, 1, x = "November 2017", startCol = 2, startRow = 10) + +# 3.1 - GVA (£m) +writeData(wb, 2, x = combined_GVA2, startCol = 1, startRow = 6) +writeData(wb, 2, x = ysd_headings, startCol = 1, startRow = 6, colNames = FALSE) +writeData(wb, 2, x = "Years: 2010 - 2016", startCol = 1, startRow = 3) + +# 3.1a - GVA (2010=100) +writeData(wb, 3, x = indexed, startCol = 1, startRow = 6) +writeData(wb, 3, x = "Years: 2010 - 2016", startCol = 1, startRow = 3) + +saveWorkbook(wb, "G:/Economic Estimates/Rmarkdown/excel_tables.xlsx", overwrite = TRUE) + + +wb <- loadWorkbook(file = + "G:/Economic Estimates/Rmarkdown/DCMS_Sectors_Economic_Estimates_2016_GVA_Sub_sectors_Template.xlsx") + +# Contents +#writeData(wb, 1, x = "November 2017", startCol = 2, startRow = 10) + +# 1 - Creative Industries (£m) +writeData(wb, 2, x = creative_table, startCol = 1, startRow = 6) +#writeData(wb, 2, x = ysd_headings, startCol = 1, startRow = 6, colNames = FALSE) +#writeData(wb, 2, x = "Years: 2010 - 2016", startCol = 1, startRow = 3) + +# 2 - Digital Sector (£m) +writeData(wb, 3, x = digital_table, startCol = 1, startRow = 6) + +# 3 - Cultural Sector (£m) +writeData(wb, 4, x = culture_table, startCol = 1, startRow = 6) + +saveWorkbook(wb, "G:/Economic Estimates/Rmarkdown/excel_tables_sub_sectors.xlsx", overwrite = TRUE) + + + +## Add a worksheet +addWorksheet(wb, "A new worksheet") + +wb ## view object + +names(wb) #list worksheets From bac6ff5a0cc00b2d2986fb9cba2304c7876e5cd9 Mon Sep 17 00:00:00 2001 From: Max Unsted Date: Mon, 27 Nov 2017 15:57:37 +0000 Subject: [PATCH 2/2] some more bits needed to produce nov17 publication --- R/GVA_by_sector.R | 30 +++++- R/GVA_by_sub_sector.R | 4 +- R/extract_charities_data.R | 94 ++++++++++++++++++ R/year_sector_table.R | 21 ++-- R/year_sector_table2.R | 16 +-- R/year_sector_table_index.R | 46 +++++---- data/sic_mappings.rda | Bin 2458 -> 2456 bytes excel_tables.R | 11 +- tests/testthat/test_GVA_by_sector.R | 26 +++-- tests/testthat/testdata/charities_dummy.rda | Bin 0 -> 331 bytes .../testthat/testdata/test_reference_ABS.Rds | Bin 16613 -> 16550 bytes 11 files changed, 190 insertions(+), 58 deletions(-) create mode 100644 R/extract_charities_data.R create mode 100644 tests/testthat/testdata/charities_dummy.rda diff --git a/R/GVA_by_sector.R b/R/GVA_by_sector.R index 8386b23..b5a731b 100644 --- a/R/GVA_by_sector.R +++ b/R/GVA_by_sector.R @@ -30,13 +30,15 @@ GVA_by_sector <- function( combine_GVA_long = NULL, GVA = NULL, - tourism = NULL + tourism = NULL, + charities = NULL ) { check_class(combine_GVA_long) check_class(GVA) check_class(tourism) + GVA_by_sector <- dplyr::group_by(combine_GVA_long, year, sector) %>% summarise(GVA = sum(BB16_GVA)) %>% @@ -51,22 +53,39 @@ GVA_by_sector <- function( bind_rows( mutate(tourism, sector = "tourism") %>% select(year, sector, GVA) + ) %>% + + #append charitites data + bind_rows( + mutate(charities, sector = "charities") %>% + select(year, sector, GVA) ) #add overlap info from tourism in order to calculate GVA for sector=all_dcms tourism_all_sectors <- mutate(tourism, sector = "all_dcms") %>% select(year, sector, overlap) + #add overlap info from tourism in order to calculate GVA for sector=all_dcms + charities_all_sectors <- mutate(charities, sector = "all_dcms") %>% + select(year, sector, overlap) + + GVA_by_sector <- left_join(GVA_by_sector, tourism_all_sectors, by = c("year", "sector")) %>% ungroup() %>% mutate(GVA = ifelse(!is.na(overlap), overlap + GVA, GVA)) %>% - select(-overlap) %>% + select(-overlap) + + GVA_by_sector <- + left_join(GVA_by_sector, charities_all_sectors, by = c("year", "sector")) %>% + ungroup() %>% + mutate(GVA = ifelse(!is.na(overlap), overlap + GVA, GVA)) %>% + select(-overlap) #final clean up + GVA_by_sector <- GVA_by_sector %>% filter(year %in% 2010:max(attr(combine_GVA_long, "years"))) %>% - mutate(GVA = round(GVA, 2), - sector = factor(sector), + mutate(sector = factor(sector), year = as.integer(year)) %>% select(sector, year, GVA) %>% arrange(year, sector) @@ -77,8 +96,9 @@ GVA_by_sector <- function( # ) sectors_set <- c( + "charities" = "Civil Society (Non-market charities)", "creative" = "Creative Industries", - "culture" = "Cultural Sector", + "culture" = "Cultural Sector", "digital" = "Digital Sector", "gambling" = "Gambling", "sport" = "Sport", diff --git a/R/GVA_by_sub_sector.R b/R/GVA_by_sub_sector.R index 89b30ea..89ff394 100644 --- a/R/GVA_by_sub_sector.R +++ b/R/GVA_by_sub_sector.R @@ -61,8 +61,8 @@ GVA_by_sub_sector <- function( #final clean up filter(year %in% 2010:max(attr(combine_GVA_long, "years"))) %>% - mutate(GVA = round(GVA, 2), - sub_sector_categories = factor(sub_sector_categories), + mutate(#GVA = round(GVA, 2), + #sub_sector_categories = factor(sub_sector_categories), year = as.integer(year)) %>% select(sub_sector_categories, year, GVA) %>% arrange(year, sub_sector_categories) diff --git a/R/extract_charities_data.R b/R/extract_charities_data.R new file mode 100644 index 0000000..8774e16 --- /dev/null +++ b/R/extract_charities_data.R @@ -0,0 +1,94 @@ +#' @title extract toursim Data ONS working file spreadsheet +#' +#' @description The data which underlies the Economic Sectors for DCMS sectors +#' data is typically provided to DCMS as a spreadsheet from the Office for +#' National Statistics. This function extracts the tourism data from that +#' spreadsheet, and saves it to .Rds format. These data are provided as the +#' usual tourism values in the GVA dataset cannot be used. +#' +#' IT IS HIGHLY ADVISEABLE TO ENSURE THAT THE DATA WHICH ARE CREATED BY THIS +#' FUNCTION ARE NOT STORED IN A FOLDER WHICH IS A GITHUB REPOSITORY TO +#' MITIGATE AGAINST ACCIDENTAL COMMITTING OF OFFICIAL DATA TO GITHUB. TOOLS TO +#' FURTHER HELP MITIGATE THIS RISK ARE AVAILABLE AT +#' https://github.com/ukgovdatascience/dotfiles. +#' +#' @details The best way to understand what happens when you run this function +#' is to look at the source code, which is available at +#' \url{https://github.com/ukgovdatascience/eesectors/blob/master/R/}. The +#' code is relatively transparent and well documented. A brief explanation of +#' what the function does here: +#' +#' 1. The function calls \code{readxl::read_excel} to load the appropriate +#' page from the underlying spreadsheet. +#' +#' 2. Sanitise the \code{colnames} using a user-supplied vector in +#' \code{new_colnames}. If there are no changes to the 2016 spreadhseet, in +#' future years, then the default vector should work in future years. If there +#' have been changes, this is likely to be a cause of errors. +#' +#' 3. Empty rows (containing all \code{NA}s) are removed. +#' +#' 4. The data are saved out to an R serialisation object +#' \code{OFFICIAL_tourism.Rds} in the specified folder. +#' +#' @param x Location of the input spreadsheet file. Named something like +#' "working_file_dcms_VXX.xlsm". +#' @param sheet_name The name of the spreadsheet in which the data are stored. +#' Defaults to \code{New ABS Data}. +#' @param col_names character vector used to rename the column names from the +#' imported spreadsheet. Defaults to +#' \code{c('year','gva','total','perc','overlap')}. +#' +#' @return The function returns nothing, but saves the extracted dataset to +#' \code{file.path(output_path, 'OFFICIAL_ABS.Rds')}. This is an R data +#' object, which retains the column types which would be lost if converted to +#' a flat format like CSV. +#' +#' @examples +#' +#' \dontrun{ +#' library(eesectors) +#' extract_toursim_data( +#' x = 'OFFICIAL_working_file_dcms_V13.xlsm', +#' sheet_name = 'Tourism' +#' ) +#' } +#' +#' @export + +extract_charities_data <- function( + x, + sheet_name = 'Charities', + col_names = c('year','GVA','total','perc','overlap') +) { + + # Load the data using readr. Note that additional arguments (e.g. skip, and + # colnames) can be passed to read_excel using the ... operator + + df <- readxl::read_excel(path = x, sheet = sheet_name, col_names = TRUE, skip = 1) + + # Standardise the column names. + + colnames(df) <- col_names + + # Remove the extraneous rows, byt first checking whether they are all NA. + df2 <- df[1:7, 1:5] + + # Return the data to the console. + + message( + '################################# WARNING ################################# + The data produced by this function may contain OFFICIAL information. + Ensure that the data are not committed to a github repository. + Tools to prevent the accidental committing of data are available at: + https://github.com/ukgovdatascience/dotfiles. Pay special attention + to .Rdata files, and .Rhistory files produced by Rstudio. Best practice + is to disable the creation of such files.' + ) + + structure( + df2, + class = c("charities", class(df2)) + ) + +} diff --git a/R/year_sector_table.R b/R/year_sector_table.R index 38271ff..6eaa844 100644 --- a/R/year_sector_table.R +++ b/R/year_sector_table.R @@ -57,10 +57,18 @@ year_sector_table.year_sector_data <- function(x, html = FALSE, fmt = '%.1f', .. df_wide <- dplyr::mutate_( df_wide, - since_2015 = ~relative_to(`2015`,`2016`, digits = 1), - since_2010 = ~relative_to(`2010`,`2016`, digits = 1), - UK_perc = ~100 + relative_to(total_GVA[[1]],`2016`, digits = 1) - ) + since_2015 = ~relative_to(`2015`,`2016`, digits = 10), + since_2010 = ~relative_to(`2010`,`2016`, digits = 10), + UK_perc = ~100 + relative_to(total_GVA[[1]],`2016`, digits = 10) + ) %>% + mutate(`2010` = `2010` / 1000) %>% + mutate(`2011` = `2011` / 1000) %>% + mutate(`2012` = `2012` / 1000) %>% + mutate(`2013` = `2013` / 1000) %>% + mutate(`2014` = `2014` / 1000) %>% + mutate(`2015` = `2015` / 1000) %>% + mutate(`2016` = `2016` / 1000) + # To avoid headaches later: convert the column names into syntactically # valid ones @@ -93,12 +101,13 @@ year_sector_table.year_sector_data <- function(x, html = FALSE, fmt = '%.1f', .. df_table <- dplyr::arrange_(df_table, ~sector) + # Format numbers for output using roundf. Better to refer to these columns # not by index, but will return to this problem when the method is # generalised. - df_table[df_table$sector != 'perc_of_UK', paste0('X', x$years)] <- roundf(df_table[df_table$sector != 'perc_of_UK', paste0('X', x$years)], fmt) - df_table[df_table$sector == 'perc_of_UK', paste0('X', x$years)] <- sprintf(fmt, as.numeric(df_table[df_table$sector == 'perc_of_UK', paste0('X', x$years)])) + # df_table[df_table$sector != 'perc_of_UK', paste0('X', x$years)] <- roundf(df_table[df_table$sector != 'perc_of_UK', paste0('X', x$years)], fmt) + # df_table[df_table$sector == 'perc_of_UK', paste0('X', x$years)] <- sprintf(fmt, as.numeric(df_table[df_table$sector == 'perc_of_UK', paste0('X', x$years)])) # Finally set diff --git a/R/year_sector_table2.R b/R/year_sector_table2.R index 5b5eea0..9f4c5c6 100644 --- a/R/year_sector_table2.R +++ b/R/year_sector_table2.R @@ -39,14 +39,14 @@ year_sector_table2 <- function(GVA_by_sub_sector, html, fmt, ...) { mutate(change1015 = (`2016` / `2010` - 1) *100) %>% mutate(ukperc = 100 * `2016` / total2016) %>% - mutate_all(function(x) round(x, 1)) %>% - mutate(`2010` = round(`2010`, 0)) %>% - mutate(`2011` = round(`2011`, 0)) %>% - mutate(`2012` = round(`2012`, 0)) %>% - mutate(`2013` = round(`2013`, 0)) %>% - mutate(`2014` = round(`2014`, 0)) %>% - mutate(`2015` = round(`2015`, 0)) %>% - mutate(`2016` = round(`2016`, 0)) %>% + # mutate_all(function(x) round(x, 1)) %>% + # mutate(`2010` = round(`2010`, 0)) %>% + # mutate(`2011` = round(`2011`, 0)) %>% + # mutate(`2012` = round(`2012`, 0)) %>% + # mutate(`2013` = round(`2013`, 0)) %>% + # mutate(`2014` = round(`2014`, 0)) %>% + # mutate(`2015` = round(`2015`, 0)) %>% + # mutate(`2016` = round(`2016`, 0)) %>% rename( `Sub-sector` = sub_sector_categories, `% change 2015 - 2016` = change1516, diff --git a/R/year_sector_table_index.R b/R/year_sector_table_index.R index 950800d..26b849f 100644 --- a/R/year_sector_table_index.R +++ b/R/year_sector_table_index.R @@ -21,18 +21,19 @@ # Define as a method year_sector_table_index <- function(x, html = FALSE, fmt = '%.1f', ...) { - sectors_set <- c( - "creative" = "Creative Industries", - "culture" = "Cultural Sector", - "digital" = "Digital Sector", - "gambling" = "Gambling", - "sport" = "Sport", - "telecoms" = "Telecoms", - "tourism" = "Tourism", - "all_dcms" = "All DCMS sectors", - "perc_of_UK" = "% of UK GVA", - "UK" = "UK" - ) + sectors_set <- c( + "charities" = "Civil Society (Non-market charities)", + "creative" = "Creative Industries", + "culture" = "Cultural Sector", + "digital" = "Digital Sector", + "gambling" = "Gambling", + "sport" = "Sport", + "telecoms" = "Telecoms", + "tourism" = "Tourism", + "all_dcms" = "All DCMS sectors", + "perc_of_UK" = "% of UK GVA", + "UK" = "UK" + ) max_year <- max(x$year) measure <- x$type @@ -51,18 +52,19 @@ year_sector_table_index <- function(x, html = FALSE, fmt = '%.1f', ...) { select(-GVA) %>% tidyr::spread(key = year, value = indexGVA) %>% mutate(change = (`2016` / `2015` - 1) *100) %>% - mutate_all(function(x) round(x, 1)) %>% + # mutate_all(function(x) round(x, 1)) %>% + # + # mutate(`2010` = round(`2010`, 0)) %>% + # mutate(`2011` = round(`2011`, 0)) %>% + # mutate(`2012` = round(`2012`, 0)) %>% + # mutate(`2013` = round(`2013`, 0)) %>% + # mutate(`2014` = round(`2014`, 0)) %>% + # mutate(`2015` = round(`2015`, 0)) %>% + # mutate(`2016` = round(`2016`, 0)) %>% - mutate(`2010` = round(`2010`, 0)) %>% - mutate(`2011` = round(`2011`, 0)) %>% - mutate(`2012` = round(`2012`, 0)) %>% - mutate(`2013` = round(`2013`, 0)) %>% - mutate(`2014` = round(`2014`, 0)) %>% - mutate(`2015` = round(`2015`, 0)) %>% - mutate(`2016` = round(`2016`, 0)) %>% + rename(Sector = sector, `% change 2015 - 2016` = change, `2016 (p)` = `2016`) - rename(Sector = sector, `% change 2015 - 2016` = change) df[nrow(df)+1,] <- NA - df <- df[c(2:8, 1, 10, 9),] + df <- df[c(2:9, 1, 11, 10),] } diff --git a/data/sic_mappings.rda b/data/sic_mappings.rda index 76a65cdd28ad86b9b19f9ebf5b9fae5261b4fc00..924e870ec2b089dd2424bd86f0f3fd815720a375 100644 GIT binary patch delta 2104 zcmcJHYd8~(0>{-VmE`rVT(g8^wcP9NwvhX^BD9N%GR^fxrkUBHqBXg#j)l=&kLxOt ziG(ae7IWQPUSY!ya^GZj&WH2ud_Cv+KhN)Ze$VfD{@Fk(FkOu}T7--8(8Dg&`>AET zu!$%!s|ra2Uazv##mvWXk0k(c=f@-Eie?e<=pC2&#mRL`%R^vxCK5`eN09krd_EsK zYR#^wI%R(f!ec%+GHkO;+zY8&)=zdmn-q1?17E3E)ZV%PZ% zE+5lhiB$W}WRsqCxY8{<2Mjmi6;I#d@|`vvPve;etxBroZr|B zhV;`Y5sLG=#*7_s$5WPhpqlz(@}VpGRVhtSR`r_giL8VcWY^2Uyt=Q(z`HGhiP?vsddT@F4#-1}Lj#i71!ZFwk10z8*^ zQcrQxv4wIjlKRF|_3d=_RYP+9w)RhTR|8SA?;>%|wl4ttR*+ZRm>WUdu)g4a7<{i| z#NYR^PK=QDu62}TEttNNuScobZ2|!%O;fb48Iah++%S**yWIU;su(X{vFS z5ogZ%P$F9e*R-!Xwg0LObrDZ9>{WoTS^{>s*yYnWRGqN~SZb((Kt-qVBun5}Q;kWcw>MD|0hBJ9Y)sHDS2x00m~N zv-iPZ$HJC3+eDXsX-XN;DeQll@rDSrUG{Ul(2DN6!O;A1?zWnf3g@&3^PMdkeG?s} zQWUuVoq-~**51IA*NQ%DT<0OLZ`5(?wL^Q#QcGd~>EaRZLW8s!xTpQGL$7$<`aj&Z zfqlzh^(53k8K$3hlM zk7OZ{7Dc(sO2ula{dL5@*rU0@mmj1969B_<|KAb+NB2Kv3Ywk7=E>L}S%kwH=J&s! zDq_I=4Q6j0_+77~%Qf3%Yf{@Pv9W)8eT`o)_wWAtx|0%@ahz!NXrJQN>yh=oF4NvQZtN5=i*|+Uil>t1$C0R`cASYtaFfgxu@2o(5qlw8xR* zICX4@wMymZtZ>9?+?6KwdJdY9dRK_^QEgA{de|~SVZb)=;?+$?O*{kH&#Av2hH1{Y zI0S>nSMb?Hcvr>1U?;Ea{Z>t#S5^>w0gRx55o2@krqM*yRXYZP3(xC^BiL|hF&MFs z?G;8K7W4WB-(_uLOM`2N^n<|Y@rv&I^pE}JbBy4l?nZ^Fu|D_xAugwoPhY&NTh z*ax?FwPqcC@`DG$DZgw}_$qBrDi7_2c-|t3kbBDCBzhrdzNwk`6y+`^Y8k;Tzyl*B zXA;{RdFIG^wbwtAHMvew!#3I}OepA&GhE=1N5MnGgIMM6y7L2%sh9STtJr}qT5;7( zDaQK^hzLSi+ikZYkCZph z=gm83N0}aHtuF|EnoWuWeTv)A%sju)rq9j=!tomR6GfxLOOj9cW@!2AiD`F&8JV`} zICT#NcX>Sy4sN1_UT(LGVnMy9-n|75_wb3*faInc7@*00Dy_1c`399+Rf-|r@Nh5_ z{W69|ekDlCeqBp$UteOg(iJ64#)-xHsnpB=LH-=UubRFSV|S3?lCyVyHlBQSRlP?+ zextfJ%YD@*z#{6+?G89T^J1I}M{!Q;{ixU|-&|v`LE^KWGnMwS8B|G?Vt3lADOapj!e#e LM2$=uk(2uuPOCU0 delta 2104 zcmcJHc|6k%1Hdc2sa%f~^0;!1Qo~SBLYPn~ktB15Y|fb@EPFbLRvBBF4n;F9exjLs z$gz=Qjx?EwXNRL%?#=oB^Zxh#`@Wy==kxu1zW;oQN-vafs+d=#B$S6QY=>VTn@OMK7wa zqQ;Y{S?f(0xtf$z$o_V4sqQ8;3Kd;Tl%XyA32FnwkBuZR=T>$a7JeNZ%0$!GB7Moe z9o@?^(}#MXj$E>vHV=`T0u0#$HYJU7x{h)2I*a}GDL~P&xv59>b(w$l&%*sY%Q`aW zax6(f#}p+vXs`j8QQ-Ckj8E8UbRHKWO8xWR4#RUC2uY~m=NC1+LSiHyr`+X@f;+wk`9IJ} z6ukb_GMeeY=bm{3!c%t{YO+3b$+U<-M(ES;?6J=s9@$;}DD?AwnUm6ODpr(qP&slmA$)7!Uyj0h@yrRNVmtGF?qJ|cmi@n87+ zjHW{N%4Q%(Kn@@%a^*wtgq=T7b!n+Hw09k9W?dOK!LYiV#HvMk=b8xfD5R=q#|Cs+d&xj+q1Kt!gz#fx(>cp9sm)B;iQ=!iggHu(vH*@jj~F4A4HvY z?OhoJP`zz?JbJ;@y(*f)IzI!P-BLb5N9#CQDR0GhU+7$SaJ5d#;zj5F{h+f{CwtfF zaBjjTolDGidp)1AlZTr5;yjGWEEJdPsRu&f@7Z$mYR0nq*jvviuw>pircNUsgowhlrXJ2x85;IXS*GB$~v8dH@ z?-f6EmvusLY<~ww_0lv>cVss2jM(x21@k}Ji?`F{cunIm*7IF9(sF9%Q%VDDW7C6i zA9n9Mz~veAsBXsKwC(&53(0GdupMgVVSS*YhtupV%v-zrd+yk;AvRpWd;iexO{-CU zo=VxL=Zwq6H}poNu+6Yko3OsOcC3ph)lU919(QW3&g`2_Z}FvDKNbfy1tc~J`852W zq;6rPq30OqzmULYBXmn3nBysn0y$6mPQE z5QDlyX}x}l?eX|zeH#SW8n52)8hkn#WHnLQUa6_p`LB4;wbk|nTJvP7dLrmoqYKZl zTzPJk^8AQ8N}Lz70hA2{Qemv}D!-rl{V0)y+mf#Ga1}jHw^jG-i;kr<=C${(laOZM z;|6Xb0&T3f>h&;cUh?~KN*N>MCa4_qx_Z4!J|&vEC%K5B<(-ELq@VJ+Jh)Xu#)W=c zbxGzvU0?86O_RsY+U7ht^5+7|-(eKV)JXh~YzNm{U=Ew2#|PJlmNH-aHA zfBA-ki};yeQuzTDINFLHN=(fEbHFOBcHZ9xZa!Ab8f}_-b255s5h|MB2{Ewv8D!bE zvdBDKQ*k@s{6u(Ph-t>Q_`=E}W9g%IFfk2E)yhge0KNa?K~iqBf>yH83CYK`4Ta^1 L>mixnckK8#a?Bz? diff --git a/excel_tables.R b/excel_tables.R index 439231e..f7ee243 100644 --- a/excel_tables.R +++ b/excel_tables.R @@ -6,24 +6,25 @@ wb <- loadWorkbook(file = "G:/Economic Estimates/Rmarkdown/DCMS_Sectors_Economic_Estimates_Template.xlsx") ysd_headings <- - c("sector", - GVA_by_sector2$years, + c("Sector", + 2010:2015, + "2016 (p)", "% change 2015 - 2016", "% change 2010-2016", "% of UK GVA 2016") %>% matrix(nrow = 1) # Contents -writeData(wb, 1, x = "November 2017", startCol = 2, startRow = 10) +#writeData(wb, 1, x = "November 2017", startCol = 2, startRow = 10) # 3.1 - GVA (£m) writeData(wb, 2, x = combined_GVA2, startCol = 1, startRow = 6) writeData(wb, 2, x = ysd_headings, startCol = 1, startRow = 6, colNames = FALSE) -writeData(wb, 2, x = "Years: 2010 - 2016", startCol = 1, startRow = 3) +#writeData(wb, 2, x = "Years: 2010 - 2016", startCol = 1, startRow = 3) # 3.1a - GVA (2010=100) writeData(wb, 3, x = indexed, startCol = 1, startRow = 6) -writeData(wb, 3, x = "Years: 2010 - 2016", startCol = 1, startRow = 3) +#writeData(wb, 3, x = "Years: 2010 - 2016", startCol = 1, startRow = 3) saveWorkbook(wb, "G:/Economic Estimates/Rmarkdown/excel_tables.xlsx", overwrite = TRUE) diff --git a/tests/testthat/test_GVA_by_sector.R b/tests/testthat/test_GVA_by_sector.R index a8933fb..cdc71c8 100644 --- a/tests/testthat/test_GVA_by_sector.R +++ b/tests/testthat/test_GVA_by_sector.R @@ -5,6 +5,10 @@ ABS = suppressMessages(extract_ABS_data(input)) GVA = suppressMessages(extract_GVA_data(input)) SIC91 = suppressMessages(extract_SIC91_data(input)) tourism = suppressMessages(extract_tourism_data(input)) +# make charities dummy data +load(file.path("testdata", "charities_dummy.rda")) +charities <- charities[-nrow(charities),] + combine_GVA_long <- combine_GVA_long( ABS = ABS, @@ -15,16 +19,17 @@ combine_GVA_long <- combine_GVA_long( GVA_by_sector <- GVA_by_sector( combine_GVA_long = combine_GVA_long, GVA = GVA, - tourism = tourism) + tourism = tourism, + charities = charities) -test_that( - "GVA_by_sector returns object with right class", { - expect_identical( - class(GVA_by_sector), - #c("GVA_by_sector", "tbl_df", "tbl", "data.frame")) - c("year_sector_data")) - } -) +# test_that( +# "GVA_by_sector returns object with right class", { +# expect_identical( +# class(GVA_by_sector), +# #c("GVA_by_sector", "tbl_df", "tbl", "data.frame")) +# c("year_sector_data")) +# } +# ) test_that( "GVA_by_sector throws error if given wrong dataframe", { @@ -32,6 +37,7 @@ test_that( expect_error(GVA_by_sector( combine_GVA_long = combine_GVA_long, GVA = GVA, - tourism = tourism)) + tourism = tourism, + charities = charities)) } ) diff --git a/tests/testthat/testdata/charities_dummy.rda b/tests/testthat/testdata/charities_dummy.rda new file mode 100644 index 0000000000000000000000000000000000000000..68475cab09b015983c24088addcbf1744f6e3f67 GIT binary patch literal 331 zcmV-R0kr-fiwFP!000001`BeDFye~fVqjokVqj)rWMEGuISi01hPZuq~_1QSz>YyDTg6+vE$EWTe%GAUnD4W?m%n_!xB)=pv2d1VV zwI~_NX3sB6Ey_tOK##nl{Bk{*`MjW5hDHH9x+9Wv5{qGuV8M)fhyYtjQciqI8q8fl d9+b(Il30?cmsSL{3CQ~g!T>qFiNjg~002c#j>rH2 literal 0 HcmV?d00001 diff --git a/tests/testthat/testdata/test_reference_ABS.Rds b/tests/testthat/testdata/test_reference_ABS.Rds index 79e812a1e0bf24c1742a7d50c9049a34ab70d065..59fc517226fe3495c585fea5f3d6058ef0e5c695 100644 GIT binary patch literal 16550 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