Skip to content

Commit

Permalink
- Add plot_time_var argument to autoplot() for 3D plotting (#197)
Browse files Browse the repository at this point in the history
  • Loading branch information
pat-s authored Jun 8, 2022
1 parent 3b04e1e commit ebcfb06
Show file tree
Hide file tree
Showing 22 changed files with 120,776 additions and 536,675 deletions.
6 changes: 3 additions & 3 deletions R/ResamplingSptCVCstf.R
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,13 @@ ResamplingSptCVCstf = R6Class("ResamplingSptCVCstf",
sample_cast = function(task, stratify = FALSE, folds) {

if (length(task$col_roles$time) && length(task$col_roles$space)) {
lg$info(sprintf("Using column roles 'space' (var. '%s') and 'time' (var. '%s') for partitioning", task$col_roles$space, task$col_roles$time))
lg$info(sprintf("Using column roles 'space' ('%s') and 'time' ('%s') for partitioning", task$col_roles$space, task$col_roles$time))

} else if (length(task$col_roles$time)) {
lg$info(sprintf("Using column role 'time' (var. '%s') for partitioning", task$col_roles$time))
lg$info(sprintf("Using column role 'time' ('%s') for partitioning", task$col_roles$time))
}
else if (length(task$col_roles$space)) {
lg$info(sprintf("Using column role 'space' (var. '%s') for partitioning", task$col_roles$space))
lg$info(sprintf("Using column role 'space' ('%s') for partitioning", task$col_roles$space))
}

target = if (stratify) task$target_names else NULL
Expand Down
25 changes: 18 additions & 7 deletions R/TaskClassifST.R
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#' @export
#' @examples
#' if (mlr3misc::require_namespaces(c("sf", "blockCV"), quietly = TRUE)) {
#'
#' data = mlr3::as_data_backend(ecuador)
#' task = TaskClassifST$new("ecuador",
#' backend = data, target = "slides",
Expand All @@ -43,7 +42,6 @@
#' }
TaskClassifST = R6::R6Class("TaskClassifST",
inherit = TaskClassif,

public = list(

#' @description
Expand All @@ -65,8 +63,8 @@ TaskClassifST = R6::R6Class("TaskClassifST",
initialize = function(id, backend, target, positive = NULL,
extra_args = list(
coords_as_features = FALSE, crs = NA,
coordinate_names = NA)) {

coordinate_names = NA
)) {
assert_string(target)

# restore extra_args defaults
Expand All @@ -85,7 +83,8 @@ TaskClassifST = R6::R6Class("TaskClassifST",

super$initialize(
id = id, backend = backend, target = target,
positive = positive, extra_args = extra_args)
positive = positive, extra_args = extra_args
)

self$extra_args$coordinate_names = extra_args$coordinate_names

Expand All @@ -98,7 +97,8 @@ TaskClassifST = R6::R6Class("TaskClassifST",

self$properties = union(
self$properties,
if (length(levels) == 2L) "twoclass" else "multiclass")
if (length(levels) == 2L) "twoclass" else "multiclass"
)
if (!is.null(positive)) {
self$positive = positive
}
Expand All @@ -116,7 +116,8 @@ TaskClassifST = R6::R6Class("TaskClassifST",
if (!extra_args$coords_as_features) {
self$col_roles$feature = setdiff(
self$col_roles$feature,
extra_args$coordinate_names)
extra_args$coordinate_names
)
}
},

Expand All @@ -138,6 +139,16 @@ TaskClassifST = R6::R6Class("TaskClassifST",
super$print(...)
cat("* Coordinates:\n")
print(self$coordinates())
if (length(self$col_roles$time) && length(self$col_roles$space)) {
cat(
"* Column roles:\n- Time:", self$col_roles$time,
"\n- Space:", self$col_roles$space, "\n"
)
} else if (length(self$col_roles$time)) {
cat("* Column roles:\n- Time:", self$col_roles$time, "\n")
} else if (length(self$col_roles$space)) {
cat("* Column roles:\n- Space:", self$col_roles$space, "\n")
}
},

#' @field extra_args (named `list()`)\cr
Expand Down
2 changes: 0 additions & 2 deletions R/TaskRegrST.R
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,6 @@ TaskRegrST = R6::R6Class("TaskRegrST",
cat("* Column roles:\n- Time:", self$col_roles$time, "\n")
} else if (length(self$col_roles$space)) {
cat("* Column roles:\n- Space:", self$col_roles$space, "\n")
} else if (length(self$col_roles$plot)) {
cat("* Column roles:\n- Plot:", self$col_roles$plot, "\n")
}
},

Expand Down
10 changes: 3 additions & 7 deletions R/autoplot.R
Original file line number Diff line number Diff line change
Expand Up @@ -1631,13 +1631,9 @@ autoplot_spatiotemp = function(
if (!plot_as_grid) {
return(invisible(plot_list))
} else {
messagef("Unfortunately plotly does not support a dynamic
arrangement of multiple subplots.
See article 'Visualization of spatiotemporal clusters'
(https://mlr3spatiotempcv.mlr-org.com/articles/spatiotemp-viz) for a
manual workaround.
Use the objects in the returned list to arrange a custom grid.",
wrap = TRUE)
lg$warn("Unfortunately plotly does not support a dynamic arrangement of multiple subplots.
See article 'Visualization of spatiotemporal clusters' (https://mlr3spatiotempcv.mlr-org.com/articles/spatiotemp-viz) for a manual workaround.
Use the objects in the returned list to arrange a custom grid.")

return(invisible(plot_list))
}
Expand Down
52 changes: 34 additions & 18 deletions R/autoplot_spcv_cstf.R
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
#' visualize mlr3 spatiotemporal resampling objects.
#'
#' @details
#' This method requires to set argument `fold_id` and no plot containing all
#' partitions can be created. This is because the method does not make use of
#' all observations but only a subset of them (many observations are left out).
#' This method requires to set argument `fold_id`.
#' No plot showing all folds in one plot can be created.
#' This is because the LLTO method does not make use of all observations but only
#' a subset of them (many observations are omitted).
#' Hence, train and test sets of one fold are not re-used in other folds as in
#' other methods and plotting these without a train/test indicator would not
#' make sense.
#' other methods and plotting these without a train/test indicator would be
#' misleading.
#'
#' @section 2D vs 3D plotting:
#' This method has both a 2D and a 3D plotting method.
Expand Down Expand Up @@ -52,6 +53,10 @@
#' @param plot3D `[logical]`\cr
#' Whether to create a 2D image via \pkg{ggplot2} or a 3D plot via
#' \pkg{plotly}.
#' @param plot_time_var `[character]`\cr
#' The variable to use for the z-axis (time).
#' Remove the column role `feature` for this variable to only use
#' it for plotting.
#' @param ... Passed down to `plotly::orca()`. Only effective when
#' `static_image = TRUE`.
#' @export
Expand All @@ -75,7 +80,7 @@
#' resampling = rsmp("sptcv_cstf", folds = 5)
#' resampling$instantiate(task_st)
#'
#' # with both `space_var` and `time_var` (LLTO), the omitted observations per
#' # with both `"space"` and `"time"` column roles set (LLTO), the omitted observations per
#' # fold can be shown by setting `show_omitted = TRUE`
#' autoplot(resampling, task_st, fold_id = 1, show_omitted = TRUE)
#' }
Expand All @@ -95,6 +100,7 @@ autoplot.ResamplingSptCVCstf = function( # nolint
static_image = FALSE,
show_omitted = FALSE,
plot3D = NULL,
plot_time_var = NULL,
...) {

dots = list(...)
Expand All @@ -118,11 +124,10 @@ autoplot.ResamplingSptCVCstf = function( # nolint
resampling_sub$instance = resampling_sub$instance[[repeats_id]]
}

# FIXME: check space and time var from column roles!
# check if we are in a 2D or 3D scenario
if (is.null(plot3D)) {
if (!is.null(resampling_sub$space_var) &&
!is.null(resampling_sub$time_var)) {
if (length(task$col_roles$space) &&
length(task$col_roles$time)) {
plot3D = TRUE
} else {
plot3D = FALSE
Expand Down Expand Up @@ -163,6 +168,18 @@ autoplot.ResamplingSptCVCstf = function( # nolint

data_coords = format_resampling_list(task, resampling_sub)

if (length(task$col_roles$time)) {
data_coords$Date = as.Date(task$data(cols = task$col_roles$time)[[1]])
} else {
# if time col is not set, check for plot_time col role
if (!is.null(plot_time_var)) {
data_coords$Date = as.Date(task$data(cols = plot_time_var)[[1]])
} else {
lg$error("Neither 'time' or 'plot' column roles are set. At least one is required for 3D plotting. If the variable is only used for plotting purposes, please define argument 'plot_time_var' in `autoplot()` and remove the column role 'feature' for this variable.")
stop()
}
}

# suppress undefined global variables note
data_coords$indicator = ""

Expand Down Expand Up @@ -303,7 +320,8 @@ autoplot.ResamplingSptCVCstf = function( # nolint
}

else {
stop("This method requires to set argument 'fold_id'. See ?autoplot.ResamplingSptCVCstf for more information.") # nolint
lg$fatal("This method requires to set argument 'fold_id'. See ?autoplot.ResamplingSptCVCstf for more information.") # nolint
stop()
}

# is a grid requested?
Expand All @@ -313,13 +331,9 @@ autoplot.ResamplingSptCVCstf = function( # nolint
}
return(plot)
} else {
messagef("Unfortunately plotly does not support a dynamic
arrangement of multiple subplots.
See article 'Visualization of spatiotemporal clusters'
(https://mlr3spatiotempcv.mlr-org.com/articles/spatiotemp-viz) for a
manual workaround.
Use the objects in the returned list to arrange a custom grid.",
wrap = TRUE)
lg$warn("Unfortunately plotly does not support a dynamic arrangement of multiple subplots.
See article 'Visualization of spatiotemporal clusters' (https://mlr3spatiotempcv.mlr-org.com/articles/spatiotemp-viz) for a manual workaround.
Use the objects in the returned list to arrange a custom grid.")

if (static_image) {
plotly::orca(plot, ...)
Expand Down Expand Up @@ -347,6 +361,7 @@ autoplot.ResamplingRepeatedSptCVCstf = function( # nolint
point_size = 3,
axis_label_fontsize = 11,
plot3D = NULL,
plot_time_var = NULL,
...) {

autoplot.ResamplingSptCVCstf(
Expand All @@ -361,7 +376,8 @@ autoplot.ResamplingRepeatedSptCVCstf = function( # nolint
nticks_y = nticks_y,
point_size = point_size,
axis_label_fontsize = axis_label_fontsize,
plot3D = plot3D,
plot3D = plot3D, ,
plot_time_var = plot_time_var,
...,
# ellipsis
repeats_id = repeats_id
Expand Down
5 changes: 0 additions & 5 deletions R/helper_autoplot.R
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,6 @@ format_resampling_list = function(task, resampling) {
data$train[data$row_id %in% row_id_train] = i
}

# FIXME: this is just an escape, fix before merging
if (length(task$col_roles$time)) {
data$Date = as.Date(task$data(cols = task$col_roles$time)[[1]])
}

# merge the coords for the 3D plot
data_coords = merge(data, coords, by = "row_id")
return(data_coords)
Expand Down
16 changes: 8 additions & 8 deletions R/zzz.R
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,17 @@ register_mlr3 = function() { # nocov start
)), "type")

# append "coordinates" to col_roles
x$task_col_roles$classif_st = append(x$task_col_roles$classif, "coordinates")
x$task_col_roles$regr_st = append(x$task_col_roles$regr, "coordinates")
# x$task_col_roles$classif_st = append(x$task_col_roles$classif, "coordinates")
# x$task_col_roles$regr_st = append(x$task_col_roles$regr, "coordinates")

# append "space" and "time" to col_roles
# used in CAST
# prevent redudant addition when calling pkgload::load_all()
if (!any(c("space", "time") %in% x$task_col_roles$classif)) {
x$task_col_roles$classif = c(x$task_col_roles$classif, "space", "time")
x$task_col_roles$regr = c(x$task_col_roles$regr, "space", "time")
x$task_col_roles$classif_st = c(x$task_col_roles$classif_st, "space", "time")
x$task_col_roles$regr_st = c(x$task_col_roles$regr_st, "space", "time")
# prevent redundant addition when calling `pkgload::load_all()`
if (!any(c("space", "time", "plot_time", "coordinates") %in% x$task_col_roles$classif)) {
x$task_col_roles$classif = append(x$task_col_roles$classif, c("coordinates", "space", "time"))
x$task_col_roles$classif_st = append(x$task_col_roles$classif_st, c("coordinates", "space", "time"))
x$task_col_roles$regr = append(x$task_col_roles$regr, c("coordinates", "space", "time"))
x$task_col_roles$regr_st = append(x$task_col_roles$regr_st, c("coordinates", "space", "time"))
}

# tasks --------------------------------------------------------------------
Expand Down
9 changes: 4 additions & 5 deletions man/TaskClassifST.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 14 additions & 6 deletions man/autoplot.ResamplingSptCVCstf.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit ebcfb06

Please sign in to comment.