diff --git a/R/tinyplot.R b/R/tinyplot.R index cbd0838f..b703fad6 100644 --- a/R/tinyplot.R +++ b/R/tinyplot.R @@ -699,11 +699,12 @@ tinyplot.default = function( deparse1(substitute(y)) } by_dep = deparse1(substitute(by)) + null_by = is.null(by) ## coerce character variables to factors if (!is.null(x) && is.character(x)) x = factor(x) if (!is.null(y) && is.character(y)) y = factor(y) - if (!is.null(by) && is.character(by)) by = factor(by) + if (!null_by && is.character(by)) by = factor(by) # flag if x==by (currently only used for "boxplot", "spineplot" and "ridges" types) x_by = identical(x, by) @@ -722,6 +723,7 @@ tinyplot.default = function( } } facet_attr = attributes(facet) ## TODO: better solution for restoring facet attributes? + null_facet = is.null(facet) if (is.null(x)) { ## Special catch for rect and segment plots without a specified y-var @@ -764,7 +766,7 @@ tinyplot.default = function( if (nrow(datapoints) > 0) { datapoints[["rowid"]] = seq_len(nrow(datapoints)) datapoints[["facet"]] = if (!is.null(facet)) facet else "" - datapoints[["by"]] = if (!is.null(by)) by else "" + datapoints[["by"]] = if (!null_by) by else "" } ## initialize empty list with information that type_data @@ -783,6 +785,8 @@ tinyplot.default = function( facet = facet, facet_by = facet_by, facet.args = facet.args, + null_by = null_by, + null_facet = null_facet, palette = palette, ribbon.alpha = ribbon.alpha, xaxt = xaxt, @@ -859,11 +863,11 @@ tinyplot.default = function( # split data by_ordered = FALSE - by_continuous = !is.null(by) && inherits(datapoints$by, c("numeric", "integer")) + by_continuous = !null_by && inherits(datapoints$by, c("numeric", "integer")) if (isTRUE(by_continuous) && type %in% c("l", "b", "o", "ribbon", "polygon", "polypath", "boxplot")) { warning("\nContinuous legends not supported for this plot type. Reverting to discrete legend.") by_continuous = FALSE - } else if (!is.null(by)) { + } else if (!null_by) { by_ordered = is.ordered(by) } @@ -878,7 +882,7 @@ tinyplot.default = function( } # aesthetics by group: col, bg, etc. - ngrps = if (is.null(by)) 1L else if (is.factor(by)) length(levels(by)) else if (by_continuous) 100L else length(unique(by)) + ngrps = if (null_by) 1L else if (is.factor(by)) length(levels(by)) else if (by_continuous) 100L else length(unique(by)) pch = by_pch(ngrps = ngrps, type = type, pch = pch) lty = by_lty(ngrps = ngrps, type = type, lty = lty) lwd = by_lwd(ngrps = ngrps, type = type, lwd = lwd) @@ -942,7 +946,7 @@ tinyplot.default = function( legend_args[["x"]] = "none" } - if (is.null(by)) { + if (null_by) { if (is.null(legend)) { legend = "none" legend_args[["x"]] = "none" @@ -1165,7 +1169,7 @@ tinyplot.default = function( # Split group-level data again to grab any "by" groups idata = split_data[[i]] iby = idata[["by"]] - if (!is.null(by)) { ## maybe all(iby=="") + if (!null_by) { ## maybe all(iby=="") if (isTRUE(by_continuous)) { idata[["col"]] = col[round(rescale_num(idata$by, from = range(datapoints$by), to = c(1, 100)))] idata[["bg"]] = bg[round(rescale_num(idata$by, from = range(datapoints$by), to = c(1, 100)))] diff --git a/R/type_barplot.R b/R/type_barplot.R index 1d024eed..944fc4ab 100644 --- a/R/type_barplot.R +++ b/R/type_barplot.R @@ -45,7 +45,7 @@ #' #' # Example for numeric y aggregated by x (default: FUN = mean) + facets #' tinyplot(extra ~ ID | group, facet = "by", data = sleep, -#' type = "barplot", beside = TRUE, fill = 0.6) +#' type = "barplot", fill = 0.6) #' #' # Fancy frequency table: #' tinyplot(Freq ~ Sex | Survived, facet = ~ Class, data = as.data.frame(Titanic), @@ -73,8 +73,9 @@ type_barplot = function(width = 5/6, beside = FALSE, center = FALSE, FUN = NULL, #' @importFrom stats aggregate data_barplot = function(width = 5/6, beside = FALSE, center = FALSE, FUN = NULL, xlevels = NULL, xaxlabels = NULL, drop.zeros = FALSE) { - fun = function(datapoints, col, bg, lty, lwd, palette, xlab = NULL, ylab = NULL, xlim = NULL, ylim = NULL, xaxt = NULL, yaxl = NULL, yaxt = NULL, axes = TRUE, facet_by = NULL, ...) { + fun = function(datapoints, col, bg, lty, lwd, palette, xlab = NULL, ylab = NULL, xlim = NULL, ylim = NULL, xaxt = NULL, yaxl = NULL, yaxt = NULL, axes = TRUE, null_by, facet_by, ...) { + ## tabulate/aggregate datapoints if (is.null(datapoints$y)) { xlab = ylab @@ -94,7 +95,7 @@ data_barplot = function(width = 5/6, beside = FALSE, center = FALSE, FUN = NULL, if (!is.factor(datapoints$by)) datapoints$by = factor(datapoints$by) if (!is.factor(datapoints$facet)) datapoints$facet = factor(datapoints$facet) - if (!beside && any(datapoints$y < 0)) { + if (isFALSE(null_by) && isFALSE(facet_by) && !beside && any(datapoints$y < 0)) { warning("'beside' must be TRUE if there are negative 'y' values") beside = TRUE } diff --git a/R/type_boxplot.R b/R/type_boxplot.R index b36dbbcb..19584370 100644 --- a/R/type_boxplot.R +++ b/R/type_boxplot.R @@ -94,7 +94,7 @@ draw_boxplot = function(range, width, varwidth, notch, outline, boxwex, staplewe data_boxplot = function() { - fun = function(datapoints, bg, col, palette, ...) { + fun = function(datapoints, bg, col, palette, null_by, null_facet, ...) { # Convert x to factor if it's not already datapoints$x = as.factor(datapoints$x) @@ -104,10 +104,6 @@ data_boxplot = function() { names(xlabs) = xlvls datapoints$x = as.integer(datapoints$x) - # Handle ordering based on by and facet variables - null_by = length(unique(datapoints$by)) == 1 - null_facet = length(unique(datapoints$facet)) == 1 - if (null_by && null_facet) { xord = order(datapoints$x) } else if (null_facet) { diff --git a/R/type_ribbon.R b/R/type_ribbon.R index 22c96323..8ae70d85 100644 --- a/R/type_ribbon.R +++ b/R/type_ribbon.R @@ -66,7 +66,7 @@ draw_ribbon = function() { data_ribbon = function(ribbon.alpha = NULL) { ribbon.alpha = sanitize_ribbon.alpha(ribbon.alpha) - fun = function(datapoints, xlabs, ...) { + fun = function(datapoints, xlabs, null_by, null_facet, ...) { # Convert x to factor if it's not already if (is.character(datapoints$x)) { datapoints$x = as.factor(datapoints$x) @@ -81,10 +81,6 @@ data_ribbon = function(ribbon.alpha = NULL) { xlabs = NULL } - # Handle ordering based on by and facet variables - null_by = length(unique(datapoints$by)) == 1 - null_facet = length(unique(datapoints$facet)) == 1 - if (null_by && null_facet) { xord = order(datapoints$x) } else if (null_facet) { diff --git a/R/type_ridge.R b/R/type_ridge.R index 1456af4d..aa492980 100644 --- a/R/type_ridge.R +++ b/R/type_ridge.R @@ -252,11 +252,11 @@ data_ridge = function(bw = "nrd0", adjust = 1, kernel = "gaussian", n = 512, col = NULL, alpha = NULL ) { - fun = function(datapoints, yaxt = NULL, ...) { + fun = function(datapoints, yaxt = NULL, null_by, ...) { # catch for special cases - anyby = length(unique(datapoints$by)) != 1 - x_by = identical(datapoints$x, datapoints$by) - y_by = identical(datapoints$y, datapoints$by) + anyby = !null_by + x_by = anyby && identical(datapoints$x, datapoints$by) + y_by = anyby && identical(datapoints$y, datapoints$by) if (x_by) { gradient = TRUE datapoints$by = "" diff --git a/R/type_spineplot.R b/R/type_spineplot.R index 1701acec..2448debe 100644 --- a/R/type_spineplot.R +++ b/R/type_spineplot.R @@ -72,7 +72,7 @@ data_spineplot = function(off = NULL, breaks = NULL, ylevels = ylevels, xaxlabel fun = function( datapoints, by = NULL, col = NULL, bg = NULL, palette = NULL, - facet = NULL, facet.args = NULL, xlim = NULL, ylim = NULL, axes = TRUE, xaxt = NULL, yaxt = NULL, + facet = NULL, facet.args = NULL, xlim = NULL, ylim = NULL, axes = TRUE, xaxt = NULL, yaxt = NULL, null_by, null_facet, ... ) { @@ -215,7 +215,7 @@ data_spineplot = function(off = NULL, breaks = NULL, ylevels = ylevels, xaxlabel if (isTRUE(y_by)) datapoints$by = factor(rep(yaxlabels, length.out = nrow(datapoints))) ## grayscale flag - grayscale = length(unique(datapoints[["by"]])) == 1 && is.null(palette) && is.null(.tpar[["palette.qualitative"]]) + grayscale = null_by && is.null(palette) && is.null(.tpar[["palette.qualitative"]]) out = list( x = c(datapoints$xmin, datapoints$xmax), @@ -227,8 +227,8 @@ data_spineplot = function(off = NULL, breaks = NULL, ylevels = ylevels, xaxlabel col = col, bg = bg, datapoints = datapoints, - by = if (length(unique(datapoints$by)) == 1) by else datapoints$by, - facet = if (length(unique(datapoints$facet)) == 1) facet else datapoints$facet, + by = if (null_by) by else datapoints$by, + facet = if (null_facet) facet else datapoints$facet, axes = FALSE, frame.plot = FALSE, xaxt = "n", diff --git a/R/type_violin.R b/R/type_violin.R index 06369a70..30b66561 100644 --- a/R/type_violin.R +++ b/R/type_violin.R @@ -78,13 +78,11 @@ type_violin = function( data_violin = function(bw = "nrd0", adjust = 1, kernel = "gaussian", n = 512, joint.bw = "none", trim = FALSE, width = 0.9) { - fun = function(datapoints, by, facet, ylab, col, bg, palette, log, ...) { + fun = function(datapoints, by, facet, ylab, col, bg, palette, log, null_by, null_facet, ...) { # Handle ordering based on by and facet variables - ngrps = length(unique(datapoints$by)) - null_by = ngrps == 1 - nfacets = length(unique(datapoints$facet)) - null_facet = nfacets == 1 + ngrps = if (null_by) 1 else length(unique(datapoints$by)) + nfacets = if (null_facet) 1 else length(unique(datapoints$facet)) # catch for special cases x_by = y_by = facet_by = FALSE diff --git a/man/type_barplot.Rd b/man/type_barplot.Rd index af0e80e3..35972f0b 100644 --- a/man/type_barplot.Rd +++ b/man/type_barplot.Rd @@ -67,7 +67,7 @@ tinytheme("clean2") # Example for numeric y aggregated by x (default: FUN = mean) + facets tinyplot(extra ~ ID | group, facet = "by", data = sleep, - type = "barplot", beside = TRUE, fill = 0.6) + type = "barplot", fill = 0.6) # Fancy frequency table: tinyplot(Freq ~ Sex | Survived, facet = ~ Class, data = as.data.frame(Titanic),