Skip to content

Commit 8fd6d2c

Browse files
committed
fix(get_run_results): call get_run_results() from within model(), addressing issue #32, and change other code using the model(), runner() and get_run_results() functions accordingly (+lint)
1 parent e762e5e commit 8fd6d2c

24 files changed

+216
-207
lines changed

DESCRIPTION

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ Imports:
2626
tidyselect,
2727
future,
2828
future.apply,
29-
ggplot2
29+
ggplot2,
30+
tibble
3031
Suggests:
3132
testthat (>= 3.0.0),
3233
patrick,

NAMESPACE

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ export(parameters)
77
export(run_scenarios)
88
export(runner)
99
export(valid_inputs)
10+
importFrom(dplyr,bind_cols)
11+
importFrom(dplyr,bind_rows)
1012
importFrom(dplyr,full_join)
1113
importFrom(dplyr,group_by)
1214
importFrom(dplyr,lead)
@@ -33,6 +35,7 @@ importFrom(simmer,timeout)
3335
importFrom(simmer,trajectory)
3436
importFrom(simmer,wrap)
3537
importFrom(stats,rexp)
38+
importFrom(tibble,tibble)
3639
importFrom(tidyr,drop_na)
3740
importFrom(tidyr,pivot_wider)
3841
importFrom(tidyselect,any_of)

R/choose_replications.R

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ confidence_interval_method <- function(replications, desired_precision, metric,
1414
yaxis_title, path, min_rep = NULL) {
1515
# Run model for specified number of replications
1616
param <- parameters(number_of_runs = replications)
17-
raw_results <- runner(param)
18-
results <- get_run_results(raw_results, param)
17+
results <- runner(param)[["run_results"]]
1918

2019
# If mean of metric is less than 1, multiply by 100
2120
if (mean(results[[metric]]) < 1L) {

R/get_run_results.R

Lines changed: 32 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
#' Get results from each replication.
1+
#' Process the raw monitored arrivals and resources.
22
#'
3-
#' For each replication (there can be one or many), calculate the: (1) number
4-
#' of arrivals, (2) mean wait time for each resource, (3) mean activity time
5-
#' for each resource, and (4) mean resource utilisation.
3+
#' For the provided replication, calculate the:
4+
#' (1) number of arrivals
5+
#' (2) mean wait time for each resource
6+
#' (3) mean activity time for each resource
7+
#' (4) mean resource utilisation.
68
#'
79
#' Credit: The utilisation calculation is taken from the
810
#' `plot.resources.utilization()` function in simmer.plot 0.1.18, which is
@@ -18,33 +20,31 @@
1820
#' @param results Named list with `arrivals` containing output from
1921
#' `get_mon_arrivals()` and `resources` containing output from
2022
#' `get_mon_resources()` (`per_resource = TRUE` and `ongoing = TRUE`).
21-
#' @param param Named list of model parameters.
23+
#' @param run_number Integer representing index of current simulation run.
2224
#'
2325
#' @importFrom dplyr group_by summarise n_distinct mutate lead full_join
26+
#' @importFrom dplyr bind_cols
2427
#' @importFrom purrr reduce
2528
#' @importFrom rlang .data
2629
#' @importFrom simmer get_mon_resources get_mon_arrivals now
2730
#' @importFrom tidyr pivot_wider drop_na
2831
#' @importFrom tidyselect any_of
32+
#' @importFrom tibble tibble
2933
#'
30-
#' @return Tibble with results from each replication.
34+
#' @return Tibble with processed results from replication.
3135
#' @export
3236

33-
get_run_results <- function(results, param) {
37+
get_run_results <- function(results, run_number) {
3438

35-
# Create a tibble with all replication numbers
36-
all_replications <- tibble::tibble(replication = 1:param[["number_of_runs"]])
39+
# Remove patients who were still waiting and had not completed
40+
results[["arrivals"]] <- results[["arrivals"]] %>%
41+
drop_na(any_of("end_time"))
3742

38-
# If there are any arrivals in any replication...
39-
if (nrow(results[["arrivals"]]) > 0) {
40-
41-
# Remove patients who were still waiting and had not completed
42-
results[["arrivals"]] <- results[["arrivals"]] %>%
43-
drop_na(any_of("end_time"))
43+
# If there are any arrivals...
44+
if (nrow(results[["arrivals"]]) > 0L) {
4445

4546
# Calculate the number of arrivals
4647
calc_arr <- results[["arrivals"]] %>%
47-
group_by(.data[["replication"]]) %>%
4848
summarise(arrivals = n_distinct(.data[["name"]]))
4949

5050
# Calculate the mean wait time for each resource
@@ -56,15 +56,15 @@ get_run_results <- function(results, param) {
5656
), 10L
5757
)
5858
) %>%
59-
group_by(.data[["resource"]], .data[["replication"]]) %>%
59+
group_by(.data[["resource"]]) %>%
6060
summarise(mean_waiting_time = mean(.data[["waiting_time"]])) %>%
6161
pivot_wider(names_from = "resource",
6262
values_from = "mean_waiting_time",
6363
names_glue = "mean_waiting_time_{resource}")
6464

6565
# Calculate the mean time spent with each resource
6666
calc_act <- results[["arrivals"]] %>%
67-
group_by(.data[["resource"]], .data[["replication"]]) %>%
67+
group_by(.data[["resource"]]) %>%
6868
summarise(mean_activity_time = mean(.data[["activity_time"]])) %>%
6969
pivot_wider(names_from = "resource",
7070
values_from = "mean_activity_time",
@@ -74,12 +74,13 @@ get_run_results <- function(results, param) {
7474
# Utilisation is given by the total effective usage time (`in_use`) over the
7575
# total time intervals considered (`dt`).
7676
calc_util <- results[["resources"]] %>%
77-
group_by(.data[["resource"]], .data[["replication"]]) %>%
77+
group_by(.data[["resource"]]) %>%
7878
# nolint start
7979
mutate(dt = lead(.data[["time"]]) - .data[["time"]]) %>%
8080
mutate(capacity = pmax(.data[["capacity"]], .data[["server"]])) %>%
8181
mutate(dt = ifelse(.data[["capacity"]] > 0L, .data[["dt"]], 0L)) %>%
82-
mutate(in_use = .data[["dt"]] * .data[["server"]] / .data[["capacity"]]) %>%
82+
mutate(in_use = (.data[["dt"]] * .data[["server"]] /
83+
.data[["capacity"]])) %>%
8384
# nolint end
8485
summarise(
8586
utilisation = sum(.data[["in_use"]], na.rm = TRUE) /
@@ -89,20 +90,18 @@ get_run_results <- function(results, param) {
8990
values_from = "utilisation",
9091
names_glue = "utilisation_{resource}")
9192

92-
# Combine all calculated metrics into a single dataframe
93-
processed_result <- list(calc_arr, calc_wait, calc_act, calc_util) %>%
94-
reduce(full_join, by = "replication")
95-
96-
# Join with all_replications to ensure all runs are represented
97-
processed_result <- dplyr::full_join(
98-
all_replications, processed_result, by = "replication") %>%
99-
# Replace NA in 'arrivals' column with 0
100-
mutate(arrivals = ifelse(is.na(arrivals), 0, arrivals))
101-
102-
# If there were no patients in any replication, return NULL
93+
# Combine all calculated metrics into a single dataframe, and along with
94+
# the replication number
95+
processed_result <- dplyr::bind_cols(
96+
tibble(replication = run_number),
97+
calc_arr, calc_wait, calc_act, calc_util
98+
)
10399
} else {
104-
processed_result <- NULL
100+
# If there were no arrivals, return dataframe row with just the replication
101+
# number and arrivals column set to 0
102+
processed_result <- tibble(replication = run_number,
103+
arrivals = nrow(results[["arrivals"]]))
105104
}
106105

107-
return(processed_result)
106+
return(processed_result) # nolint
108107
}

R/model.R

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
#' @importFrom stats rexp
1313
#' @importFrom utils capture.output
1414
#'
15-
#' @return Named list with two tables: monitored arrivals and resources
15+
#' @return Named list with two tables: three tables: monitored arrivals,
16+
#' monitored resources, and the processed results from the run.
1617
#' @export
1718

1819
model <- function(run_number, param, set_seed = TRUE) {
@@ -70,7 +71,7 @@ model <- function(run_number, param, set_seed = TRUE) {
7071
resources = get_mon_resources(env)
7172
)
7273

73-
if (nrow(result[["arrivals"]]) > 0) {
74+
if (nrow(result[["arrivals"]]) > 0L) {
7475
# Replace replication with appropriate run number (as these functions
7576
# assume, if not supplied with list of envs, that there was one replication)
7677
result[["arrivals"]][["replication"]] <- run_number
@@ -84,5 +85,8 @@ model <- function(run_number, param, set_seed = TRUE) {
8485
NA))
8586
}
8687

88+
# Calculate the average results for that run and add to result list
89+
result[["run_results"]] <- get_run_results(result, run_number)
90+
8791
return(result)
8892
}

R/runner.R

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
#'
55
#' @importFrom future plan multisession sequential
66
#' @importFrom future.apply future_lapply
7+
#' @importFrom dplyr bind_rows
78
#'
8-
#' @return Named list with two tables: monitored arrivals and resources.
9+
#' @return Named list with three tables: monitored arrivals, monitored
10+
#' resources, and the processed results from each run.
911
#' @export
1012

1113
runner <- function(param) {
@@ -44,7 +46,14 @@ runner <- function(param) {
4446
all_resources <- do.call(
4547
rbind, lapply(results, function(x) x[["resources"]])
4648
)
47-
results <- list(arrivals = all_arrivals, resources = all_resources)
49+
# Bind rows will fill NA - e.g. if some runs have no results columns
50+
# as had no arrivals, will set those to NA for that row
51+
all_run_results <- dplyr::bind_rows(
52+
lapply(results, function(x) x[["run_results"]])
53+
)
54+
results <- list(arrivals = all_arrivals,
55+
resources = all_resources,
56+
run_results = all_run_results)
4857
}
4958

5059
return(results) # nolint

R/scenarios.R

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,8 @@ run_scenarios <- function(scenarios, base_list) {
4040
s_param[[name]] <- s_args[[name]]
4141
}
4242

43-
# Run replications for the current scenario and process results
44-
raw_results <- runner(s_param)
45-
scenario_result <- get_run_results(raw_results, s_param)
43+
# Run replications for the current scenario and get processed results
44+
scenario_result <- runner(s_param)[["run_results"]]
4645

4746
# Append scenario parameters to the results
4847
scenario_result[["scenario"]] <- index

man/get_run_results.Rd

Lines changed: 9 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/model.Rd

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/runner.Rd

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)