diff --git a/NAMESPACE b/NAMESPACE index 72501b30..0029cf7c 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -58,6 +58,7 @@ importFrom(stats,na.omit) importFrom(stats,terms) importFrom(stats,update) importFrom(tools,file_ext) +importFrom(utils,globalVariables) importFrom(utils,head) importFrom(utils,modifyList) importFrom(utils,tail) diff --git a/R/get_saved_par.R b/R/get_saved_par.R index be3b1ef0..ede49387 100644 --- a/R/get_saved_par.R +++ b/R/get_saved_par.R @@ -102,14 +102,14 @@ #' tpar(sp) #' #' @export -get_saved_par <- function(when = c("before", "after")) { +get_saved_par = function(when = c("before", "after")) { when = match.arg(when) par_env_name = paste0(".saved_par_", when) return(get(par_env_name, envir = get(".tinyplot_env", envir = parent.env(environment())))) } # (non-exported) companion function(s) for setting the original pars -set_saved_par <- function(when = c("before", "after"), value) { +set_saved_par = function(when = c("before", "after"), value) { when = match.arg(when) par_env_name = paste0(".saved_par_", when) assign(par_env_name, value, envir = get(".tinyplot_env", envir = parent.env(environment()))) diff --git a/R/histogram.R b/R/histogram.R deleted file mode 100644 index b433c835..00000000 --- a/R/histogram.R +++ /dev/null @@ -1,97 +0,0 @@ -histogram_args = function(x, by, facet, facet_by, dots, ylab, col, bg, fill, ribbon.alpha) { - hbreaks = ifelse(!is.null(dots[["breaks"]]), dots[["breaks"]], "Sturges") - hist_list = hist(x, breaks = hbreaks, plot = FALSE) - - if (!is.null(by) || !is.null(facet)) { - split_type = ifelse(is.null(facet) || isTRUE(facet_by), "byonly", ifelse(is.null(by), "facetonly", "byandfacet")) - - if (split_type == "byonly") { - split_x = split(x, by) - } else if (split_type == "facetonly") { - split_x = split(x, facet) - } else { - split_x = split(x, interaction(by, facet, sep = "___")) - } - - hist_split = lapply(seq_along(split_x), function(s) { - h = hist(split_x[[s]], breaks = hist_list$breaks, plot = FALSE) - h$breaks = h$breaks[-1] - - if (split_type %in% c("byonly", "byandfacet")) { - h$by = rep(names(split_x)[[s]], length(h$breaks)) - } else { - h$by = NULL - } - - if (split_type %in% c("facetonly", "byandfacet")) { - h$facet = rep(names(split_x)[[s]], length(h$breaks)) - } else if (isTRUE(facet_by)) { - h$facet = h$by - } else { - h$facet = NULL - } - return(h) - }) - - hist_list = do.call(Map, c(c, hist_split)) - xmin = hist_list$breaks - xmax = hist_list$mids + (hist_list$mids - hist_list$breaks) - by = hist_list$by - - if (split_type == "byandfacet") by = sub("___.*$", "", by) - facet = hist_list$facet - - if (split_type == "byandfacet") facet = sub(".*___", "", facet) - if (!is.null(facet)) facet = as.factor(facet) - } else { - xmin = hist_list$breaks[-1] - xmax = hist_list$mids + (hist_list$mids - hist_list$breaks[-1]) - } - - ymin = hist_list$counts - - # Optional: remove zero count cases - if (!is.null(by) || !is.null(facet)) { - hidx = which(ymin != 0) - xmin = xmin[hidx] - xmax = xmax[hidx] - ymin = ymin[hidx] - by = by[hidx] - facet = facet[hidx] - } - - ymax = rep(0, length(ymin)) - x = c(xmin, xmax) - y = c(ymin, ymax) - - if (is.null(ylab)) ylab = "Frequency" - if (is.null(by) && is.null(palette)) { - if (is.null(col)) col = par("fg") - if (is.null(bg) && is.null(fill)) bg = "lightgray" - } else { - if (is.null(bg) && !is.null(fill)) bg = fill - if (is.null(bg)) { - bg = ribbon.alpha - } - } - - type = "rect" - - out = list( - x = x, - y = y, - ymin = ymin, - ymax = ymax, - xmin = xmin, - xmax = xmax, - ylab = ylab, - col = col, - bg = bg, - type = type, - by = by, - facet = facet, - hbreaks = hbreaks, - hist_list = hist_list - ) - return(out) -} diff --git a/R/lim.R b/R/lim.R index 7b84012e..81c3dad0 100644 --- a/R/lim.R +++ b/R/lim.R @@ -1,20 +1,19 @@ # calculate limits of each plot -lim_args = function(...) { - list2env(list(...), environment()) +lim_args = function(datapoints, xlim, ylim, palette, col, bg, fill, type) { - xy = xy.coords(x = x, y = y) - if (is.null(xlim)) xlim = range(xy$x[is.finite(xy$x)]) - if (is.null(ylim)) ylim = range(xy$y[is.finite(xy$y)]) + if (all(c("x", "y") %in% names(datapoints))) { + xy = xy.coords(x = datapoints$x, y = datapoints$y) + if (is.null(xlim)) xlim = range(xy$x[is.finite(xy$x)]) + if (is.null(ylim)) ylim = range(xy$y[is.finite(xy$y)]) + } - if (!is.null(xmin)) xlim[1] = min(c(xlim, xmin)) - if (!is.null(xmax)) xlim[2] = max(c(xlim, xmax)) - if (!is.null(ymin)) ylim[1] = min(c(ylim, ymin)) - if (!is.null(ymax)) ylim[2] = max(c(ylim, ymax)) + xlim = range(c(xlim, datapoints[["xmin"]], datapoints[["xmax"]]), finite = TRUE) + ylim = range(c(ylim, datapoints[["ymin"]], datapoints[["ymax"]]), finite = TRUE) if (type == "boxplot") { xlim = xlim + c(-0.5, 0.5) - if (is.null(by) && is.null(palette)) { + if (length(unique(datapoints[["by"]])) == 1 && is.null(palette)) { if (is.null(col)) col = par("fg") if (is.null(bg) && is.null(fill)) bg = "lightgray" } else { @@ -22,6 +21,13 @@ lim_args = function(...) { } } - return(as.list(environment())) + out = list( + xlim = xlim, + ylim = ylim, + col = col, + bg = bg, + fill = fill) + + return(out) } diff --git a/R/tinyformula.R b/R/tinyformula.R index d64edeac..56fd546e 100644 --- a/R/tinyformula.R +++ b/R/tinyformula.R @@ -44,11 +44,11 @@ tinyformula = function(formula, facet = NULL) { } if (!is.null(xfacet)) { environment(xfacet) = environment(formula) - xfacet[[2L]] <- facet[[length(facet)]] + xfacet[[2L]] = facet[[length(facet)]] } if (!is.null(yfacet)) { environment(yfacet) = environment(formula) - yfacet[[2L]] <- facet[[2L]] + yfacet[[2L]] = facet[[2L]] } ## combine everything @@ -69,7 +69,7 @@ tinyformula = function(formula, facet = NULL) { )) } -tinyframe <- function(formula, data, drop = FALSE) { +tinyframe = function(formula, data, drop = FALSE) { ## input ## - formula: (sub-)formula ## - data: model.frame from full formula diff --git a/R/tinyplot.R b/R/tinyplot.R index f08cd8a9..c60bfda5 100644 --- a/R/tinyplot.R +++ b/R/tinyplot.R @@ -528,6 +528,7 @@ tinyplot.default = function( # sanitize arguments ribbon.alpha = sanitize_ribbon.alpha(ribbon.alpha) type = sanitize_type(type, x, y) + was_area_type = identical(type, "area") # flag to keep track for some legend adjustments below palette = substitute(palette) @@ -637,76 +638,46 @@ tinyplot.default = function( return(do.call(tinyplot.density, args = fargs)) } - if (type == "histogram") { - fargs = histogram_args( - x = x, by = by, facet = facet, facet_by = facet_by, dots = dots, - ylab = ylab, col = col, bg = bg, fill = fill, ribbon.alpha = ribbon.alpha) + datapoints = list(x = x, y = y, xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax) + datapoints = Filter(function(z) length(z) > 0, datapoints) + datapoints = data.frame(datapoints) + datapoints[["rowid"]] = seq_len(nrow(datapoints)) + datapoints[["facet"]] = if (!is.null(facet)) facet else "" + datapoints[["by"]] = if (!is.null(by)) by else "" + + # jitter is standalone: before and in addition to type = "point" + if (type == "jitter") { + fargs = type_jitter(datapoints) list2env(fargs, environment()) } - if (type == "area") { - ymax = y - ymin = rep.int(0, length(y)) - type = "ribbon" - was_area_type = TRUE - } else { - was_area_type = FALSE # flag to keep track for some legend adjustments below - } + if (type == "histogram") { + fargs = type_histogram( + x = x, by = by, facet = facet, dots = dots, + ylab = ylab, col = col, bg = bg, fill = fill, ribbon.alpha = ribbon.alpha, datapoints = datapoints) + list2env(fargs, environment()) - if (type == "jitter") { - fargs = jitter_args(x = x, y = y) + } else if (type == "area") { + fargs = type_area(datapoints) + list2env(fargs, environment()) + + } else if (type == "boxplot") { + fargs = type_boxplot(datapoints = datapoints) + list2env(fargs, environment()) + + } else if (type == "ribbon") { + fargs = type_ribbon(datapoints = datapoints, xlabs = xlabs) list2env(fargs, environment()) - } - if (type == "boxplot") x = as.factor(x) - if (type %in% c("pointrange", "errorbar", "ribbon", "boxplot")) { - if (is.character(x)) x = as.factor(x) - if (is.factor(x)) { - ## For non-boxplots... Need to maintain order that was observed in the - ## original data (i.e., no new sorting by factor) - if (type != "boxplot") { - xlvls = unique(x) - x = factor(x, levels = xlvls) - } else { - xlvls = levels(x) - } - xlabs = seq_along(xlvls) - names(xlabs) = xlvls - x = as.integer(x) - } - if (type %in% c("ribbon", "boxplot")) { - if (is.null(by) && is.null(facet)) { - xord = order(x) - } else if (is.null(facet)) { - xord = order(by, x) - by = by[xord] - } else if (is.null(by)) { - facet_grid = attr(facet, "facet_grid") - xord = order(facet, x) - facet = facet[xord] - attr(facet, "facet_grid") = facet_grid - } else { - facet_grid = attr(facet, "facet_grid") - xord = order(by, facet, x) - by = by[xord] - facet = facet[xord] - attr(facet, "facet_grid") = facet_grid - } - x = x[xord] - y = y[xord] - ymin = ymin[xord] - ymax = ymax[xord] - rm(xord) - } + } else if (type %in% c("pointrange", "errorbar")) { + fargs = type_pointrange(datapoints = datapoints, xlabs = xlabs) + list2env(fargs, environment()) } # plot limits fargs = lim_args( - x = x, xlim = xlim, xmax = xmax, xmin = xmin, - y = y, ylim = ylim, ymax = ymax, ymin = ymin, - type = type, - col = col, bg = bg, by = by, fill = fill, palette = palette - ) + datapoints = datapoints, xlim = xlim, ylim = ylim, palette = palette, + col = col, bg = bg, fill = fill, type = type) list2env(fargs, environment()) @@ -720,24 +691,16 @@ tinyplot.default = function( by_ordered = is.ordered(by) } - if (!is.null(by) && !by_continuous) { - split_data = list(x = x, y = y) - split_data[["xmin"]] = xmin - split_data[["xmax"]] = xmax - split_data[["ymin"]] = ymin - split_data[["ymax"]] = ymax - split_data[["facet"]] = facet - split_data = lapply(split_data, split, by) - split_data = do.call(function(...) Map("list", ...), split_data) + if (length(unique(datapoints$facet)) == 1) { + datapoints[["facet"]] = NULL + } + if (!by_continuous) { + split_data = split(datapoints, datapoints$by) + split_data = lapply(split_data, as.list) } else { - split_data = list(list( - x = x, y = y, - xmin = xmin, xmax = xmax, - ymin = ymin, ymax = ymax, - facet = facet - )) + split_data = list(as.list(datapoints)) } - + # aesthetics by group: col, bg, etc. aesthetics_args = aesthetics( adjustcolor = adjustcolor, alpha = alpha, bg = bg, by = by, @@ -972,15 +935,6 @@ tinyplot.default = function( idata = split_data[[i]] ifacet = idata[["facet"]] if (!is.null(ifacet)) { - idata[["facet"]] = NULL ## Don't need this anymore since we'll be splitting by ifacet - ## Need extra catch for non-groupby data that also doesn't have ymin or - ## ymax vars - if (is.null(by) || isTRUE(by_continuous)) { - if (is.null(idata[["xmin"]])) idata[["xmin"]] = NULL - if (is.null(idata[["xmax"]])) idata[["xmax"]] = NULL - if (is.null(idata[["ymin"]])) idata[["ymin"]] = NULL - if (is.null(idata[["ymax"]])) idata[["ymax"]] = NULL - } if (isTRUE(by_continuous)) { idata[["col"]] = col[round(rescale_num(by, to = c(1, 100)))] idata[["bg"]] = bg[round(rescale_num(by, to = c(1, 100)))] diff --git a/R/type_area.R b/R/type_area.R new file mode 100644 index 00000000..cc9a714c --- /dev/null +++ b/R/type_area.R @@ -0,0 +1,11 @@ +type_area = function(datapoints) { + datapoints$ymax = datapoints$y + datapoints$ymin = rep.int(0, nrow(datapoints)) + out = list( + datapoints = datapoints, + ymax = datapoints$ymax, + ymin = datapoints$ymin, + type = "ribbon" + ) + return(out) +} \ No newline at end of file diff --git a/R/type_boxplot.R b/R/type_boxplot.R new file mode 100644 index 00000000..dc935a40 --- /dev/null +++ b/R/type_boxplot.R @@ -0,0 +1,41 @@ +type_boxplot = function(datapoints) { + # Convert x to factor if it's not already + datapoints$x = as.factor(datapoints$x) + + # Handle factor levels and maintain order + xlvls = levels(datapoints$x) + xlabs = seq_along(xlvls) + 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) { + xord = order(datapoints$by, datapoints$x) + } else if (null_by) { + xord = order(datapoints$facet, datapoints$x) + } else { + xord = order(datapoints$by, datapoints$facet, datapoints$x) + } + + # Reorder x, y, ymin, and ymax based on the order determined + datapoints = datapoints[xord,] + + # Return the result as a list called 'out' + out = list( + x = datapoints$x, + y = datapoints$y, + ymin = datapoints$ymin, + ymax = datapoints$ymax, + xlabs = xlabs, + datapoints = datapoints) + + if (length(unique(datapoints$by)) > 1) out[["by"]] = datapoints$by + if (length(unique(datapoints$facet)) > 1) out[["facet"]] = datapoints$facet + + return(out) +} diff --git a/R/density.R b/R/type_density.R similarity index 100% rename from R/density.R rename to R/type_density.R diff --git a/R/type_histogram.R b/R/type_histogram.R new file mode 100644 index 00000000..2bf58f73 --- /dev/null +++ b/R/type_histogram.R @@ -0,0 +1,52 @@ +type_histogram = function(x, by, facet, dots, ylab, col, bg, fill, ribbon.alpha, datapoints) { + hbreaks = ifelse(!is.null(dots[["breaks"]]), dots[["breaks"]], "Sturges") + hist_list = hist(x, breaks = hbreaks, plot = FALSE) + + if (is.null(ylab)) ylab = "Frequency" + if (is.null(by) && is.null(palette)) { + if (is.null(col)) col = par("fg") + if (is.null(bg) && is.null(fill)) bg = "lightgray" + } else { + if (is.null(bg) && !is.null(fill)) bg = fill + if (is.null(bg)) { + bg = ribbon.alpha + } + } + + type = "rect" + + datapoints_breaks = hist(datapoints$x, breaks = hbreaks, plot = FALSE) + datapoints = split(datapoints, list(datapoints$by, datapoints$facet)) + datapoints = Filter(function(k) nrow(k) > 0, datapoints) + + datapoints = lapply(datapoints, function(k) { + h = hist(k$x, breaks = datapoints_breaks$breaks, plot = FALSE) + out = data.frame( + by = k$by[1], # already split + facet = k$facet[1], # already split + ymin = 0, + ymax = h$counts, + xmin = h$breaks[-1], + xmax = h$mids + (h$mids - h$breaks[-1]) + ) + return(out) + }) + datapoints = do.call(rbind, datapoints) + + out = list( + x = c(datapoints$xmin, datapoints$xmax), + y = c(datapoints$ymin, datapoints$ymax), + ymin = datapoints$ymin, + ymax = datapoints$ymax, + xmin = datapoints$xmin, + xmax = datapoints$xmax, + ylab = ylab, + col = col, + bg = bg, + type = type, + datapoints = datapoints, + by = if (length(unique(datapoints$by)) == 1) by else datapoints$by, + facet = if (length(unique(datapoints$facet)) == 1) facet else datapoints$facet + ) + return(out) +} diff --git a/R/jitter.R b/R/type_jitter.R similarity index 62% rename from R/jitter.R rename to R/type_jitter.R index 86ecb04a..76d5e6cd 100644 --- a/R/jitter.R +++ b/R/type_jitter.R @@ -1,4 +1,6 @@ -jitter_args = function(x, y) { +type_jitter = function(datapoints) { + x = datapoints$x + y = datapoints$y if (is.character(x)) x = as.factor(x) if (is.character(y)) y = as.factor(y) if (is.factor(x)) { @@ -19,6 +21,17 @@ jitter_args = function(x, y) { } x = jitter(x) y = jitter(y) - type = "p" - return(as.list(environment())) + + datapoints$x = x + datapoints$y = y + + out = list( + datapoints = datapoints, + x = x, + y = y, + xlabs = xlabs, + ylabs = ylabs, + type = "p" + ) + return(out) } diff --git a/R/type_pointrange.R b/R/type_pointrange.R new file mode 100644 index 00000000..e19214ba --- /dev/null +++ b/R/type_pointrange.R @@ -0,0 +1,17 @@ +type_pointrange = function(datapoints, xlabs) { + if (is.character(datapoints$x)) datapoints$x = as.factor(datapoints$x) + if (is.factor(datapoints$x)) { + ## original data (i.e., no new sorting by factor) + xlvls = unique(datapoints$x) + datapoints$x = factor(datapoints$x, levels = xlvls) + xlabs = seq_along(xlvls) + names(xlabs) = xlvls + datapoints$x = as.integer(datapoints$x) + } + out = list( + x = datapoints$x, + xlabs = xlabs, + datapoints = datapoints) + + return(out) +} \ No newline at end of file diff --git a/R/type_ribbon.R b/R/type_ribbon.R new file mode 100644 index 00000000..06288c2f --- /dev/null +++ b/R/type_ribbon.R @@ -0,0 +1,45 @@ +type_ribbon = function(datapoints, xlabs) { + # Convert x to factor if it's not already + if (is.character(datapoints$x)) { + datapoints$x = as.factor(datapoints$x) + } + + if (is.factor(datapoints$x)) { + xlvls = levels(datapoints$x) + xlabs = seq_along(xlvls) + names(xlabs) = xlvls + datapoints$x = as.integer(datapoints$x) + } else { + 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) { + xord = order(datapoints$by, datapoints$x) + } else if (null_by) { + xord = order(datapoints$facet, datapoints$x) + } else { + xord = order(datapoints$by, datapoints$facet, datapoints$x) + } + + # Reorder x, y, ymin, and ymax based on the order determined + datapoints = datapoints[xord,] + + out = list( + x = datapoints$x, + y = datapoints$y, + ymin = datapoints$ymin, + ymax = datapoints$ymax, + xlabs = xlabs, + datapoints = datapoints) + + if (length(unique(datapoints$by)) > 1) out[["by"]] = datapoints$by + if (length(unique(datapoints$facet)) > 1) out[["facet"]] = datapoints$facet + + return(out) +} diff --git a/R/zzz.R b/R/zzz.R index 3d83e40d..f928623c 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -1,3 +1,9 @@ +#' Operations on package load +#' @importFrom utils globalVariables +#' @param libname library name +#' @param pkgname package name name +#' @keywords internal +#' @noRd .onLoad = function(libname, pkgname) { # https://stackoverflow.com/questions/12598242/global-variables-in-packages-in-r @@ -36,6 +42,48 @@ assign(".saved_par_before", NULL, envir = get(".tinyplot_env", envir = parent.env(environment()))) assign(".saved_par_after", NULL, envir = get(".tinyplot_env", envir = parent.env(environment()))) - utils::globalVariables(c("cex_fct_adj", "facets", "nfacet_cols", "nfacet_rows", "nfacets", "oxaxis", "oyaxis")) - + globalVariables(c( + "add", + "asp", + "axes", + "by_continuous", + "by_ordered", + "cex_fct_adj", + "dots", + "facet_bg", + "facet_border", + "facet_col", + "facet_font", + "facet_newlines", + "facet_rect", + "facet_text", + "facet.args", + "facet", + "facets", + "fill", + "frame.plot", + "has_legend", + "ifacet", + "nfacet_cols", + "nfacet_rows", + "nfacets", + "ngrps", + "oxaxis", + "oyaxis", + "ribbon.alpha", + "split_data", + "type", + "x", + "xaxt", + "xlabs", + "xlim", + "xlvls", + "xmax", + "xmin", + "y", + "yaxt", + "ylim", + "ymax", + "ymin" + )) } diff --git a/inst/tinytest/test-segments.R b/inst/tinytest/test-segments.R index 9ed22dec..d502d03c 100644 --- a/inst/tinytest/test-segments.R +++ b/inst/tinytest/test-segments.R @@ -3,7 +3,7 @@ using("tinysnapshot") # test case adapted from ?segments Examples set.seed(42L) -x = stats::runif(12); y <- stats::rnorm(12) +x = stats::runif(12); y = stats::rnorm(12) i = order(x, y); x = x[i]; y = y[i] s = seq(length(x)-1) # one shorter than data s = s[-length(s)] diff --git a/man/tinyplot.Rd b/man/tinyplot.Rd index 08d9cfb8..b19f95a7 100644 --- a/man/tinyplot.Rd +++ b/man/tinyplot.Rd @@ -1,40 +1,13 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/density.R, R/tinyplot.R -\name{tinyplot.density} -\alias{tinyplot.density} +% Please edit documentation in R/tinyplot.R, R/type_density.R +\name{tinyplot} \alias{tinyplot} \alias{tinyplot.default} \alias{tinyplot.formula} \alias{plt} +\alias{tinyplot.density} \title{Lightweight extension of the base R plotting function} \usage{ -\method{tinyplot}{density}( - x = NULL, - by = NULL, - facet = NULL, - facet.args = NULL, - type = c("l", "area"), - xlim = NULL, - ylim = NULL, - main = NULL, - sub = NULL, - xlab = NULL, - ylab = NULL, - ann = par("ann"), - axes = TRUE, - frame.plot = axes, - asp = NA, - grid = NULL, - pch = NULL, - col = NULL, - lty = NULL, - lwd = NULL, - bg = NULL, - fill = NULL, - restore.par = FALSE, - ... -) - tinyplot(x, ...) \method{tinyplot}{default}( @@ -113,6 +86,33 @@ tinyplot(x, ...) ) plt(x, ...) + +\method{tinyplot}{density}( + x = NULL, + by = NULL, + facet = NULL, + facet.args = NULL, + type = c("l", "area"), + xlim = NULL, + ylim = NULL, + main = NULL, + sub = NULL, + xlab = NULL, + ylab = NULL, + ann = par("ann"), + axes = TRUE, + frame.plot = axes, + asp = NA, + grid = NULL, + pch = NULL, + col = NULL, + lty = NULL, + lwd = NULL, + bg = NULL, + fill = NULL, + restore.par = FALSE, + ... +) } \arguments{ \item{x, y}{the x and y arguments provide the x and y coordinates for the @@ -122,6 +122,10 @@ likely the names of existing vectors or columns of data frames. See the \code{\link[grDevices]{xy.coords}} for details. If supplied separately, \code{x} and \code{y} must be of the same length.} +\item{...}{other graphical parameters (see \code{\link[graphics]{par}}), or +arguments passed to the relevant plot type (e.g., \code{breaks} for +\code{type = "histogram"}, or \code{varwidth} for \code{type = "boxplot"}).} + \item{by}{grouping variable(s). The default behaviour is for groups to be represented in the form of distinct colours, which will also trigger an automatic legend. (See \code{legend} below for customization options.) However, @@ -177,6 +181,9 @@ and background. Default values for these arguments are inherited from features globally for all \code{tinyplot} plots. }} +\item{data}{a data.frame (or list) from which the variables in formula +should be taken. A matrix is converted to a data frame.} + \item{type}{character string giving the type of plot desired. If no argument is provided, then the plot type will default to something sensible for the type of \code{x} and \code{y} inputs (i.e., usually \code{"p"}). Options are: @@ -208,6 +215,10 @@ the range of the \code{finite} values to be plotted should be used.} \item{ylim}{the y limits of the plot.} +\item{log}{a character string which contains "x" if the x axis is to be +logarithmic, "y" if the y axis is to be logarithmic and "xy" or "yx" if +both axes are to be logarithmic.} + \item{main}{a main title for the plot, see also \code{title}.} \item{sub}{a subtitle for the plot.} @@ -244,80 +255,6 @@ with better default behaviour. The default behaviour is determined by (and can be set globally through) the value of \code{tpar("grid")}. }} -\item{pch}{plotting "character", i.e., symbol to use. Character, integer, or -vector of length equal to the number of categories in the \code{by} variable. -See \code{pch}. In addition, users can supply a special \code{pch = "by"} convenience -argument, in which case the characters will automatically loop over the -number groups. This automatic looping will begin at the global character -value (i.e., \code{par("pch")}) and recycle as necessary.} - -\item{col}{plotting color. Character, integer, or vector of length equal to -the number of categories in the \code{by} variable. See \code{col}. Note that the -default behaviour in \code{tinyplot} is to vary group colors along any variables -declared in the \code{by} argument. Thus, specifying colors manually should not -be necessary unless users wish to override the automatic colors produced by -this grouping process. Typically, this would only be done if grouping -features are deferred to some other graphical parameter (i.e., passing the -"by" keyword to one of \code{pch}, \code{lty}, \code{lwd}, or \code{bg}; see below.)} - -\item{lty}{line type. Character, integer, or vector of length equal to the -number of categories in the \code{by} variable. See \code{lty}. In addition, users -can supply a special \code{lty = "by"} convenience argument, in which case the -line type will automatically loop over the number groups. This automatic -looping will begin at the global line type value (i.e., \code{par("lty")}) and -recycle as necessary.} - -\item{lwd}{line width. Numeric scalar or vector of length equal to the -number of categories in the \code{by} variable. See \code{lwd}. In addition, users -can supply a special \code{lwd = "by"} convenience argument, in which case the -line width will automatically loop over the number of groups. This -automatic looping will be centered at the global line width value (i.e.,} - -\item{bg}{background fill color for the open plot symbols 21:25 (see -\code{points.default}), as well as ribbon and area plot types. For the latter -group---including filled density plots---an automatic alpha transparency -adjustment will be applied (see the \code{ribbon.alpha} argument further below). -Users can also supply either one of two special convenience arguments that -will cause the background fill to inherit the automatic grouped coloring -behaviour of \code{col}: -\itemize{ -\item \code{bg = "by"} will insert a background fill that inherits the main color -mappings from \code{col}. -\item \verb{by = } (i.e., a numeric in the range \verb{[0,1]}) will insert -a background fill that inherits the main color mapping(s) from \code{col}, but -with added alpha-transparency. -} - -For both of these convenience arguments, note that the (grouped) \code{bg} -mappings will persist even if the (grouped) \code{col} defaults are themselves -overridden. This can be useful if you want to preserve the grouped palette -mappings by background fill but not boundary color, e.g. filled points. See -examples.} - -\item{fill}{alias for \code{bg}. If non-NULL values for both \code{bg} and \code{fill} are -provided, then the latter will be ignored in favour of the former.} - -\item{restore.par}{a logical value indicating whether the -\code{\link[graphics]{par}} settings prior to calling \code{tinyplot} should be -restored on exit. Defaults to FALSE, which makes it possible to add -elements to the plot after it has been drawn. However, note the the outer -margins of the graphics device may have been altered to make space for the -\code{tinyplot} legend. Users can opt out of this persistent behaviour by -setting to TRUE instead. See also \link{get_saved_par} for another option to -recover the original \code{\link[graphics]{par}} settings, as well as -longer discussion about the trade-offs involved.} - -\item{...}{other graphical parameters (see \code{\link[graphics]{par}}), or -arguments passed to the relevant plot type (e.g., \code{breaks} for -\code{type = "histogram"}, or \code{varwidth} for \code{type = "boxplot"}).} - -\item{data}{a data.frame (or list) from which the variables in formula -should be taken. A matrix is converted to a data frame.} - -\item{log}{a character string which contains "x" if the x axis is to be -logarithmic, "y" if the y axis is to be logarithmic and "xy" or "yx" if -both axes are to be logarithmic.} - \item{palette}{one of the following options: \itemize{ \item NULL (default), in which case the palette will be chosen according to @@ -363,6 +300,59 @@ specifying "none"). legend arguments, e.g. "bty", "horiz", and so forth. }} +\item{pch}{plotting "character", i.e., symbol to use. Character, integer, or +vector of length equal to the number of categories in the \code{by} variable. +See \code{pch}. In addition, users can supply a special \code{pch = "by"} convenience +argument, in which case the characters will automatically loop over the +number groups. This automatic looping will begin at the global character +value (i.e., \code{par("pch")}) and recycle as necessary.} + +\item{lty}{line type. Character, integer, or vector of length equal to the +number of categories in the \code{by} variable. See \code{lty}. In addition, users +can supply a special \code{lty = "by"} convenience argument, in which case the +line type will automatically loop over the number groups. This automatic +looping will begin at the global line type value (i.e., \code{par("lty")}) and +recycle as necessary.} + +\item{lwd}{line width. Numeric scalar or vector of length equal to the +number of categories in the \code{by} variable. See \code{lwd}. In addition, users +can supply a special \code{lwd = "by"} convenience argument, in which case the +line width will automatically loop over the number of groups. This +automatic looping will be centered at the global line width value (i.e.,} + +\item{col}{plotting color. Character, integer, or vector of length equal to +the number of categories in the \code{by} variable. See \code{col}. Note that the +default behaviour in \code{tinyplot} is to vary group colors along any variables +declared in the \code{by} argument. Thus, specifying colors manually should not +be necessary unless users wish to override the automatic colors produced by +this grouping process. Typically, this would only be done if grouping +features are deferred to some other graphical parameter (i.e., passing the +"by" keyword to one of \code{pch}, \code{lty}, \code{lwd}, or \code{bg}; see below.)} + +\item{bg}{background fill color for the open plot symbols 21:25 (see +\code{points.default}), as well as ribbon and area plot types. For the latter +group---including filled density plots---an automatic alpha transparency +adjustment will be applied (see the \code{ribbon.alpha} argument further below). +Users can also supply either one of two special convenience arguments that +will cause the background fill to inherit the automatic grouped coloring +behaviour of \code{col}: +\itemize{ +\item \code{bg = "by"} will insert a background fill that inherits the main color +mappings from \code{col}. +\item \verb{by = } (i.e., a numeric in the range \verb{[0,1]}) will insert +a background fill that inherits the main color mapping(s) from \code{col}, but +with added alpha-transparency. +} + +For both of these convenience arguments, note that the (grouped) \code{bg} +mappings will persist even if the (grouped) \code{col} defaults are themselves +overridden. This can be useful if you want to preserve the grouped palette +mappings by background fill but not boundary color, e.g. filled points. See +examples.} + +\item{fill}{alias for \code{bg}. If non-NULL values for both \code{bg} and \code{fill} are +provided, then the latter will be ignored in favour of the former.} + \item{alpha}{a numeric in the range \verb{[0,1]} for adjusting the alpha channel of the color palette, where 0 means transparent and 1 means opaque. Use fractional values, e.g. \code{0.5} for semi-transparency.} @@ -372,6 +362,16 @@ giving the amount by which plotting characters and symbols should be scaled relative to the default. Note that NULL is equivalent to 1.0, while NA renders the characters invisible.} +\item{restore.par}{a logical value indicating whether the +\code{\link[graphics]{par}} settings prior to calling \code{tinyplot} should be +restored on exit. Defaults to FALSE, which makes it possible to add +elements to the plot after it has been drawn. However, note the the outer +margins of the graphics device may have been altered to make space for the +\code{tinyplot} legend. Users can opt out of this persistent behaviour by +setting to TRUE instead. See also \link{get_saved_par} for another option to +recover the original \code{\link[graphics]{par}} settings, as well as +longer discussion about the trade-offs involved.} + \item{xmin, xmax, ymin, ymax}{minimum and maximum coordinates of relevant area or interval plot types. Only used when the \code{type} argument is one of \code{"rect"} or \code{"segments"} (where all four min-max coordinates are required),