# Some commonly used functions
factors_in_prams <- function(x) {
# x - list
# if (inherits(x, "list")) y <- lapply()
# browser()
y <- lapply(x, function(y) any(sapply(y@data, class) == "factors"))
y[unlist(y)]
}
# factors_in_prams(scen_BASE_int@modInp@parameters)
nonchar_in_sets <- function(x) {
# x - list
# if (inherits(x, "list")) y <- lapply()
# browser()
y <- lapply(x, function(y) any(class(y) != "character"))
y[unlist(y)]
}
# nonchar_in_sets(scen_BASE_int@modInp@set)
# scen_BASE_int@modInp@set$year |> class()
#' Size of an object
#'
#' @param x any R object
#' @param level1 logical, if TRUE, the function will return the size of the
#' object and its slots (if any)
#' @param units character, units to display the size, default is "auto"
#' @param sort logical, if TRUE, the function will sort the slots by size
#' @param decreasing logical, if TRUE, the function will sort the slots in
#' decreasing order
#' @param byteTol numeric, threshold in bytes to filter the slots
#' @param asNumeric logical, if TRUE, the function will return the size of the
#' object and its slots in bytes
#'
#' @return character value or vector, size of the object or its slots
#' @export
#'
#' @examples
#' size(1)
#' size(rep(1, 1e3))
#' size(rep(1L, 1e3))
size <- function(x, level1 = FALSE, units = "auto", sort = TRUE,
decreasing = FALSE, byteTol = 0, asNumeric = FALSE) {
# browser()
if (!level1) {
format(object.size(x), units = units)
} else {
if (isS4(x)) { # S4
slx <- slotNames(x)
val <- lapply(slx, function(z) {
object.size(slot(x, z))
})
names(val) <- slx
# return(val)
} else if (is.list(x)) {
val <- lapply(x, function(z) {
object.size(z)
})
} else {
format(object.size(x), units = units)
}
vv <- lapply(val, as.numeric) # in bytes
if (sort) {
ii <- order(unlist(vv), decreasing = decreasing)
val <- val[ii]
vv <- vv[ii]
}
if (asNumeric) {
val <- vv
} else {
val <- lapply(val, function(z) {
format(z, units = units)
})
}
# browser()
ii <- vv >= byteTol
val[ii]
}
}
if (F) { # Check
size(scen, 1, "Mb", byteTol = 1024)
size(scen@modInp, 1, "Mb", byteTol = 1024)
size(scen@modInp@parameters, 1, "Mb", byteTol = 1024 * 1000)
size(scen@modInp@parameters$pTradeIrEff, 1, "Mb", byteTol = 1024 * 1000)
size(scen@modInp@parameters$pTradeIrEff@data, 1, "Mb", byteTol = 0, asNumeric = TRUE)
head(scen@modInp@parameters$pTradeIrEff@data)
}
dir_size <- function(path) {
if (!dir.exists(path)) {
stop("Directory '", path, "' does not exist")
}
files <- list.files(path, recursive = TRUE, full.names = TRUE)
sizes <- file.size(files)
# sum(file.info(list.files(".", all.files = TRUE, recursive = TRUE))$size)
return(sum(sizes))
}
.fix_path <- function(x) {
# gsub("[\\/]+", "/", paste0(x, "/"))
gsub("[\\/]+", "/", x)
}
fp <- function(...) {
file.path(...) |> .fix_path()
# normalizePath(winslash = "/", mustWork = FALSE)
}
#' Check validity of object's names used in sets
#'
#' @param x character, name of an object of `energyRt`
#'
#' @return logical, TRUE if the name is valid.
#' @export
#'
#' @examples
#' check_name("name")
#' check_name("1name")
#' check_name("name1")
#' check_name("name_1")
#' check_name("name_1!")
check_name <- function(x) {
(length(x) != 1 || !is.character(x) ||
sub("^[[:alpha:]][[:alnum:]_]*$", "", x) == "")
}
#' Function to find duplicated values in interpolated scenario.
#'
#' @param x scenario or data.frame with data to check.
#'
#' @return data.frame with duplicated values.
#' @export
#'
#' @examples
#' \dontrun{
#' findDuplicates(scen_BASE)
#' }
findDuplicates <- function(x) {
if (is(x, 'scenario')) {
rs <- NULL
for (pr in names(x@modInp@parameters))
if (x@modInp@parameters[[pr]]@type %in% c('numpar', 'bounds')) {
tmp <- x@modInp@parameters[[pr]]@data
tmp <- tmp[, -ncol(tmp), drop = FALSE]
fl <- duplicated(tmp)
if (any(fl)) {
tmp <- tmp[fl,, drop = FALSE]
tmp$parameter <- pr
tmp <- tmp[, c(ncol(tmp), 1:(ncol(tmp) - 1)), drop = FALSE]
rs <- rbind(rs, tmp)
}
}
if (!is.null(rs)) {
cat(paste0("Found ", length(unique(rs$parameter)),
" tables with duplicates, ", nrow(rs),
" duplicated rows in total\n"))
return(invisible(rs))
}
}
findDuplicates0 <- function(x) {
check_by_slots <- function(x, slt_name) {
rs <- NULL
for (i in slt_name) {
slt <- slot(x, i)
set_slot <- colnames(slt)[
colnames(slt) %in% c('acomm',
.set_al[
!(.set_al %in% c('dem'))
])]
value_slot <- colnames(slt)[!(colnames(slt) %in% set_slot)]
fl <- !is.na(slt[, value_slot, drop = FALSE])
if (any(fl)) {
for (j in value_slot[apply(fl, 2, any)]) {
f2 <- duplicated(slt[fl[, j], set_slot, drop = FALSE])
if (any(f2)) {
rs <- rbind(rs, data.frame(slot = i, parameter = j,
value = sum(f2),
stringsAsFactors = FALSE))
}
}
}
}
return(rs)
}
res <- data.frame(repository = character(), object = character(),
slot = character(), parameter = character(),
stringsAsFactors = FALSE)
if (is(x, 'model')) {
rs <- NULL
for (i in seq_along(x@data)) {
tmp <- findDuplicates0(x@data[[i]])
if (!is.null(tmp)) {
tmp$repository <- x@data[[i]]@name
rs <- rbind(rs, tmp)
}
}
tmp <- findDuplicates0(x@config)
if (!is.null(tmp)) {
tmp$repository <- '-'
tmp$object <- 'config'
rs <- rbind(rs, tmp[, c(ncol(tmp), 2:ncol(tmp) - 1)])
}
if (is.null(rs)) return(NULL)
return(rs[, c(ncol(rs), 1:(ncol(rs) - 1))])
} else
if (is(x, 'repository')) {
rs <- NULL
for (i in seq_along(x@data)) {
tmp <- findDuplicates0(x@data[[i]])
if (!is.null(tmp)) {
tmp$object <- x@data[[i]]@name
rs <- rbind(rs, tmp)
}
}
if (is.null(rs)) return(NULL)
return(rs[, c(ncol(rs), 1:(ncol(rs) - 1))])
} else
if (inherits(x, c('tax', 'sub', 'weather', 'supply',
'import', 'export', 'trade', 'technology',
'demand', 'storage'))) {
slt_name <- getSlots(class(x))
slt_name <- names(slt_name)[
slt_name == 'data.frame' &
!(names(slt_name) %in% c('input', 'output', 'aux'))]
return(check_by_slots(x, slt_name))
} else if (is(x, c('constraint'))) {
tmp <- check_by_slots(x, c('rhs', 'for.each'))
for (y in seq_along(x@lhs)) {
nn <- check_by_slots(x@lhs[[y]], 'mult')
if (!is.null(nn)) {
nn$slot <- paste('lhs', y, nn$slot)
tmp <- rbind(tmp, nn)
}
}
return(tmp)
} else if (is(x, "costs")) {
tmp <- check_by_slots(x, c('for.sum', 'for.each', 'mult'))
return(tmp)
} else if (inherits(x, c('slice', 'commodity'))) {
} else if (is(x, 'config')) {
return(check_by_slots(x, c('debug', 'discount')))
} else warning(paste0('Unknown class "', class(x), '"'))
NULL
}
rs <- findDuplicates0(x)
if (!is.null(rs)) {
# cat(paste0("There are ", nrow(rs), " duplicates, sum of values: ", sum(rs$value), "\n"))
cat(paste0("Found ", nrow(rs), " tables with duplicates,",
sum(rs$value), "duplicated rows in total\n"))
return(invisible(rs))
}
}
fact2char <- function(df, asTibble = TRUE) {
stopifnot(is.data.frame(df))
jj <- sapply(df, is.factor)
for (j in names(df)[jj]) {
df[[j]] <- as.character(df[[j]])
}
if (asTibble) {df <- as_tibble(df)}
df
}
#' Switch on/off and select/customize progress bar
#'
#' @param type character, type of the progress bar to display. Existing options:
#' "bw", "default", "cli", "progress".
#' @param show logical, the progress bar is visible if `TRUE`.
#' @param clear logical, sets `progressr.clear` global option. If `TRUE`, all outout from the progress bar will be cleared.
#'
#' @rdname progress
#' @return sets the progress bar and returns `NULL`
#' @export
#'
#' @examples
#' \dontrun{
#' set_progress_bar("bw")
#' set_progress_bar("default")
#' set_progress_bar("cli")
#' set_progress_bar("progress")
#' set_progress_bar("pbcol")
#' }
set_progress_bar <- function(type = "bw", show = TRUE, clear = FALSE) {
if (interactive()) progressr::handlers(global = show)
options(progressr.clear = clear)
if (is.null(type)) return(invisible(NULL))
if (type == "bw") {
progressr::handlers(
progressr::handler_pbcol(
# adjust = 1.0,
# complete = function(s) cli::bg_br_green(cli::col_br_black(s)),
complete = function(s) cli::bg_black(cli::col_white(s)),
# complete = function(s) cli::bg_br_black(cli::col_silver(s)),
incomplete = function(s) cli::bg_none(cli::col_grey(s))
# incomplete = function(s) cli::bg_black(cli::col_white(s))
)
)
} else if (type == "default") {
progressr::handlers("txtprogressbar")
} else if (type == "pbcol") {
progressr::handlers(
progressr::handler_pbcol(
adjust = 1.0,
complete = function(s) cli::bg_red(cli::col_black(s)),
incomplete = function(s) cli::bg_cyan(cli::col_black(s))
)
)
} else if (type == "cli") {
progressr::handlers("cli")
} else if (type == "progress") {
progressr::handlers("progress")
} else {
warning(
"Unrecognized 'type = ", type, "'\n",
"See `https://progressr.futureverse.org/` for detailed customization.")
}
}
#' @rdname progress
#' @export
#'
#' @examples
#' \dontrun{
#' show_progress_bar()
#' show_progress_bar(FALSE)
#' }
show_progress_bar <- function(show = TRUE) {
if (interactive()) set_progress_bar(type = NULL, show = show)
}
#' Set or get directory for/with scenarios
#'
#' @param path character, path to the directory with scenarios,
#' default is `NULL`
#'
#' @family options
#' @return sets or gets the path to the directory with scenarios
#' @export
#' @rdname options
#'
#' @examples
#' \dontrun{
#' set_scenarios_path("path/to/scenarios")
#' get_scenarios_path()
#' }
set_scenarios_path <- function(path = NULL) {
options::opt_set("scenarios_path", path)
# options(en_scenarios_path = path)
}
#' @family options
#' @export
#' @rdname options
get_scenarios_path <- function() {
options::opt("scenarios_path")
# getOption("en_scenarios_path")
}
# merge_paths <- function(path1, path2)
#' Drop columns in a data.frame with all NA values
#'
#' @description
#' A wrapper with `dplyr` functions to drop columns with no information (all `NA` values)
#'
#' @param x data.frame
#' @param unique logical, if TRUE (default), `unique()` function will be applied to the result.
#'
#' @return data.frame with dropped columns
#' @export
#'
#' @examples
#' x <- data.frame(a = c(1, 2, NA), b = c(NA, NA, NA), c = c(NA, 2, 3))
#' drop_na_cols(x)
#'
drop_na_cols <- function(x, unique = TRUE) {
x <- select(x, where(~ !all(is.na(.))))
if (unique) x <- unique(x)
x
}
#' Make a name for a scenario directory
#' @description A function to automate the creation of a scenario directory name.
#' Used internally in `solve*()` and `interpolate*()` functions.
#' Also can be used to amend the name of the scenario directory and explicitly
#' assign the directory name to save the scenario object.
#'
#' @param scen scenario object
#' @param name character, name of the scenario, default is `scen@name`
#' @param model_name character, name of the model, default is `scen@model@name`
#' @param calendar_name character, name of the calendar, default is `scen@settings@calendar@name`
#' @param horizon_name character, name of the horizon, default is `scen@settings@horizon@name`
#' @param prefix character, prefix to add to the name
#' @param suffix character, suffix to add to the name
#' @param sep character, separator, default is `_`
#'
#' @return character, name of the scenario directory
#' @export
#'
#' @examples
#' \dontrun{
#' make_scenario_dirname(scen_BASE)
#' make_scenario_dirname(scen_BASE, prefix = "prefix", suffix = "suffix")
#' }
#'
make_scenario_dirname <- function(
scen,
name = scen@name,
model_name = scen@model@name,
calendar_name = scen@settings@calendar@name,
horizon_name = scen@settings@horizon@name,
prefix = NULL,
suffix = NULL,
sep = "_"
) {
if (isTRUE(nchar(prefix) > 0)) {
name <- paste(prefix, name, sep = sep)
}
if (isTRUE(is.null(name) && nchar(name) == 0)) {
warning("Scenario name is empty. Using 'scenario' as a default name.")
name <- "scenario"
}
if (isTRUE(nchar(model_name) > 0)) {
name <- paste(name, model_name, sep = sep)
}
if (isTRUE(nchar(calendar_name) > 0)) {
name <- paste(name, calendar_name, sep = sep)
}
if (isTRUE(nchar(horizon_name) > 0)) {
name <- paste(name, horizon_name, sep = sep)
}
if (isTRUE(nchar(suffix) > 0)) {
name <- paste(name, suffix, sep = sep)
}
return(name)
}
fEAC <- function(invcost, discount, olife) {
stopifnot(olife > 0)
stopifnot(invcost > 0)
if (round(discount, 7) == 0) {
return(invcost/olife)
}
(invcost * discount) / (1 - (1 + discount) ^ (-olife))
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.