Skip to content

Commit

Permalink
abort for empty data
Browse files Browse the repository at this point in the history
  • Loading branch information
Yunuuuu committed Jan 6, 2025
1 parent d3e60ca commit 8e89f1d
Show file tree
Hide file tree
Showing 13 changed files with 105 additions and 30 deletions.
3 changes: 3 additions & 0 deletions R/align-.R
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,9 @@ Align <- ggproto("Align", AlignProto,
# we always regard rows as the observations
if (is.null(layout_nobs)) {
layout_nobs <- NROW(data)
if (layout_nobs == 0L) {
cli_abort("{.arg data} cannot be empty", call = self$call)
}
} else if (NROW(data) != layout_nobs) {
cli_abort(sprintf(
"%s (nobs: %d) is not compatible with the %s (nobs: %d)",
Expand Down
8 changes: 7 additions & 1 deletion R/align-group.R
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,13 @@ align_group <- function(group, active = NULL) {

#' @importFrom ggplot2 ggproto
AlignGroup <- ggproto("AlignGroup", Align,
nobs = function(self, params) vec_size(.subset2(params, "group")),
nobs = function(self, params) {
nobs <- vec_size(.subset2(params, "group"))
if (nobs == 0L) {
cli_abort("{.arg group} cannot be empty", call = self$call)
}
nobs
},
setup_params = function(self, nobs, params) {
assert_mismatch_nobs(
self, nobs, self$nobs(params),
Expand Down
10 changes: 8 additions & 2 deletions R/align-hclust.R
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,17 @@ AlignHclust <- ggproto("AlignHclust", Align,
nobs = function(self, params) {
if (inherits(tree <- .subset2(params, "method"), "hclust")) {
self$labels <- .subset2(tree, "labels")
length(.subset2(tree, "order"))
nobs <- length(.subset2(tree, "order"))
} else { # a dendrogram
self$labels <- labels(tree)
stats::nobs(tree)
nobs <- stats::nobs(tree)
}
if (nobs == 0L) {
cli_abort("tree defined in {.arg method} cannot be empty",
call = self$call
)
}
nobs
},
compute = function(self, panel, index, distance, method, use_missing,
reorder_dendrogram, k = NULL, h = NULL, cutree = NULL) {
Expand Down
8 changes: 7 additions & 1 deletion R/align-order.R
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,13 @@ align_order <- function(weights = rowMeans, ...,
#' @importFrom ggplot2 ggproto
#' @importFrom rlang inject is_atomic
AlignOrder <- ggproto("AlignOrder", Align,
nobs = function(params) length(.subset2(params, "weights")),
nobs = function(self, params) {
nobs <- length(.subset2(params, "weights"))
if (nobs == 0L) {
cli_abort("{.arg weights} cannot be empty", call = self$call)
}
nobs
},
setup_params = function(self, nobs, params) {
if (!is.function(weights <- .subset2(params, "weights"))) {
assert_mismatch_nobs(
Expand Down
5 changes: 5 additions & 0 deletions R/cross-.R
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ Cross <- ggproto("Cross", AlignProto,
if (is.null(data)) {
design["nobs"] <- list(NULL)
} else {
if (NROW(data) == 0L) {
cli_abort("{.arg data} cannot be empty",
call = self$call
)
}
design["nobs"] <- list(NROW(data))
}
}
Expand Down
23 changes: 14 additions & 9 deletions R/ggalign.R
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,16 @@ AlignGg <- ggproto("AlignGg", AlignProto,
}
plot_data <- inject(fortify_data_frame(data, !!!self$params))


# for discrete design, # we need ensure the nobs is the same
if (is_discrete_design(design <- layout@design)) {
if (!is.null(data)) {
if (is.null(layout_nobs <- design$nobs)) {
layout_nobs <- NROW(data)
if (layout_nobs == 0L) {
cli_abort("{.arg data} cannot be empty",
call = self$call
)
}
} else if (NROW(data) != layout_nobs) {
cli_abort(sprintf(
"%s (nobs: %d) is not compatible with the %s (nobs: %d)",
Expand Down Expand Up @@ -199,7 +203,9 @@ AlignGg <- ggproto("AlignGg", AlignProto,
data <- self$data

# if inherit from the parent layout
if (isTRUE(self$use_extra_design) && is_discrete_design(extra_design)) {
if (isTRUE(self$use_extra_design) &&
is_discrete_design(extra_design) &&
!is.null(.subset2(extra_design, "nobs"))) {
# if the data is inherit from the `quad_layout()`
# the data must be a matrix
extra_plot_data <- data_frame0(
Expand All @@ -218,14 +224,13 @@ AlignGg <- ggproto("AlignGg", AlignProto,
}
return(gguse_data(plot, data))
} else if (is.null(.subset2(design, "nobs"))) {
cli_abort(
c(
"you must provide {.arg data} to initialize the layout",
i = sprintf("no data was found in %s", self$layout_name),
i = "Or you should use {.fn ggfree}"
cli_abort(c(
sprintf(
"you must initialize %s before drawing %s",
self$layout_name, object_name(self)
),
call = self$call
)
i = "Or you should use {.fn ggfree}"
), call = self$call)
}
direction <- self$direction
axis <- to_coord_axis(direction)
Expand Down
6 changes: 6 additions & 0 deletions R/ggcross.R
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ CrossGg <- ggproto("CrossGg", AlignProto,
#' @importFrom stats reorder
build_plot = function(self, plot, design, extra_design = NULL,
previous_design = NULL) {
if (is.null(.subset2(design, "nobs"))) {
cli_abort(sprintf(
"you must initialize %s before drawing %s",
self$layout_name, object_name(self)
), call = self$call)
}
direction <- self$direction
index <- vec_c(
.subset2(previous_design, "index"),
Expand Down
8 changes: 6 additions & 2 deletions R/ggfree.R
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,9 @@ FreeGg <- ggproto("FreeGg", AlignProto,
if (is.null(data)) {
return(gguse_data(plot, data))
}
if (isTRUE(self$use_extra_design) && is_discrete_design(extra_design)) {
if (isTRUE(self$use_extra_design) &&
is_discrete_design(extra_design) &&
!is.null(.subset2(extra_design, "nobs"))) {
extra_plot_data <- data_frame0(
.extra_panel = .subset2(extra_design, "panel"),
.extra_index = .subset2(extra_design, "index")
Expand All @@ -137,7 +139,9 @@ FreeGg <- ggproto("FreeGg", AlignProto,
}

# if inherit from the parent layout
if (isTRUE(self$use_design) && is_discrete_design(design)) {
if (isTRUE(self$use_design) &&
is_discrete_design(design) &&
!is.null(.subset2(design, "nobs"))) {
plot_data <- data_frame0(
.panel = .subset2(design, "panel"),
.index = .subset2(design, "index"),
Expand Down
11 changes: 4 additions & 7 deletions R/ggmark.R
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,10 @@ MarkGg <- ggproto("MarkGg", AlignProto,
build_plot = function(self, plot, design, extra_design = NULL,
previous_design = NULL) {
if (is.null(.subset2(design, "nobs"))) {
cli_abort(
c(
"you must provide {.arg data} to initialize the layout",
i = sprintf("no data was found in %s", self$layout_name)
),
call = self$call
)
cli_abort(sprintf(
"you must initialize %s before drawing %s",
self$layout_name, object_name(self)
), call = self$call)
}
mark <- self$mark

Expand Down
13 changes: 13 additions & 0 deletions R/layout-chain-.R
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,13 @@ chain_layout_add.QuadLayout <- function(object, layout, object_name) {
"{.arg data} in %s must return a {.cls matrix}",
object_name(object)
))
} else {
if (NROW(data) == 0L || ncol(data) == 0L) {
cli_abort(sprintf(
"{.arg data} in %s return an empty matrix",
object_name(object)
))
}
}
}
# we initialize the `nobs` of the extra_design for the
Expand Down Expand Up @@ -442,6 +449,12 @@ chain_layout_add.QuadLayout <- function(object, layout, object_name) {
object_name(object)
))
}
if (NROW(data) == 0L || ncol(data) == 0L) {
cli_abort(sprintf(
"{.arg data} in %s return an empty matrix",
object_name(object)
))
}
}
# set the `nobs` for `quad_layout()`
if (is_horizontal(direction)) {
Expand Down
6 changes: 6 additions & 0 deletions R/layout-quad-.R
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,12 @@ new_quad_layout <- function(name, data, xlim = waiver(), ylim = waiver(),
if (!is.waive(data) && !is.function(data)) {
nrows <- NROW(data)
ncols <- ncol(data)

# for data has dimention but one dimention is 0
# as.matrix(data.frame(row.names = letters))
if (nrows == 0L || ncols == 0L) {
cli_abort("empty data is no allowed")
}
} else {
nrows <- NULL
ncols <- NULL
Expand Down
28 changes: 20 additions & 8 deletions R/layout-quad-build.R
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,27 @@ quad_build.QuadLayout <- function(quad, schemes = NULL, theme = NULL,
data <- quad@data
row_design <- setup_design(quad@horizontal)
column_design <- setup_design(quad@vertical)
if ((is_discrete_design(row_design) || is_discrete_design(column_design)) &&
(is.function(data) || is.waive(data))) {
if (is.function(data)) {
cli_abort(c(
sprintf(
"You must provide the {.arg data} argument to plot %s.",
"{.arg data} cannot be a {.cls function}",
i = sprintf(
"Did you want to add %s to a {.fn stack_layout}?",
object_name(quad)
),
i = "To align discrete variables, data is required to initialize the layout."
)
))
}
if (is_discrete_design(row_design) &&
is.null(.subset2(row_design, "nobs"))) {
cli_abort(sprintf(
"you must initialize %s before drawing the main plot",
object_name(quad),
))
}
if (is_discrete_design(column_design) &&
is.null(.subset2(column_design, "nobs"))) {
cli_abort(sprintf(
"you must initialize %s before drawing the main plot",
object_name(quad),
))
}
schemes <- inherit_parent_layout_schemes(quad, schemes)
Expand Down Expand Up @@ -225,8 +238,7 @@ quad_build_data <- function(data, row_design, column_design) {
if (is.null(data) ||
(is_continuous_design(row_design) &&
is_continuous_design(column_design))) {
# ggplot use waiver() to indicates the NULL data
return(data %||% waiver())
return(data)
}
if (is_discrete_design(row_design)) {
row_panel <- .subset2(row_design, "panel")
Expand Down
6 changes: 6 additions & 0 deletions R/layout-stack-.R
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ stack_discrete.default <- function(direction, data = NULL, ...,
if (!is.null(data) && !is.function(data)) {
# if we have provided data, we initialize the `nobs`
nobs <- vec_size(data)

# for data has dimention but one dimention is 0
# as.matrix(data.frame(row.names = letters))
if (nobs == 0L) {
cli_abort("empty data is no allowed")
}
} else {
nobs <- NULL
}
Expand Down

0 comments on commit 8e89f1d

Please sign in to comment.