\name{XY}
\alias{XY}
\alias{Plot}
\alias{ScatterPlot}
\alias{sp}

\title{Scatterplots including Time Series}

\description{

\code{lessR} introduces the concept of an \emph{analytic view} visualization function, in which the choice of visualization function directly reflects the structure of the data and the analyst's intent for understanding the data. The function \code{XY()} visualizes the joint distribution of two continuous variables,
or more generally the relationship among multiple variables, along with associated
summary statistics. The specific representation is selected with the
\code{form} argument:
\itemize{
  \item Scatterplot of points with \code{form="scatter"} (default)
  \item Smoothed scatterplot with \code{form="smooth"}
  \item Hexbin scatterplot with \code{form="hexbin"}
  \item Contour plot (2-dimensional density display) with \code{form="contour"}
}

For the standard scatterplot, stratification divides the data into groups
via the arguments \code{by} and \code{facet}. The \code{by} argument overlays
groups in a single coordinate system for direct comparison, while
\code{facet} produces coordinated small multiples on separate panels.
\code{XY()} requires continuous \code{x} and \code{y}. When the continuous
\code{x} is ordered in time, such as a date or an equal-interval sequence,
successive points are connected to form a time-series display. Relationships
between two categorical variables, such as bubble plots, are instead handled
by \code{\link{Chart}} with \code{form="bubble"} and a \code{by} variable.

When running in RStudio, static graphics are drawn in the \code{Plots}
window. When the default \code{use_plotly=TRUE}, the interactive
\pkg{plotly} version of the scatterplot (including time series) display is also drawn in the \code{Viewer} window.

A scatterplot displays the joint values of one or more variables as points
in an \(n\)-dimensional coordinate system, in which the coordinates of each
point are the values of \(n\) variables for a single observation (row of
data). With a common syntax, \code{XY(x, y, ...)} generates a family of
related 1- or 2-dimensional relationship plots, possibly enhanced with
fitted lines, ellipses, and outlier labeling. Categorical variables should
typically be defined as factors, and date variables should be stored as
\code{Date} objects. When \code{x} is of class \code{Date}, the display is
treated as a time-indexed series.

\code{XY()} therefore serves as the relationship-oriented counterpart to
\code{Chart()} (aggregated values) and \code{X()} (univariate distributions)
within the three-function visualization framework implemented in \pkg{lessR}.
}

\usage{
XY(

    # -------------------------------------------------------
    # Data from which to construct the plot for x- and y-axis
    x, y, data=d, filter=NULL,

    # ----------------------------------------------------
    # Stratification: Same (by) or separate panels (facet)
    by=NULL,
    facet=NULL, n_row=NULL, n_col=NULL, aspect="fill",

    # -----------------------------------
    # Geometric forms of relational plots
    form=c("scatter", "smooth", "contour", "hexbin"),


    # -------------------------------
    # Enhancements and customizations
    # -------------------------------

    # --------------------------------------------------------------------
    # Analogy of physical Marks on paper that create the points and labels
    # See  ?style  for more options with the  style()  function
    theme=getOption("theme"),
    fill=NULL, color=NULL,
    transparency=getOption("trans_pt_fill"),

    # -----------------------------------------------
    # Plotted points and any connecting line segments
    enhance=FALSE, means=TRUE,
    pt_size=NULL, pt_size_cut=NULL, pt_shape="circle", line_width=1.5,
    segments=FALSE, segments_y=FALSE, segments_x=FALSE,

    # ----------------------
    # Sort and jitter points
    sort=c("0", "-", "+"),
    jitter_x=NULL, jitter_y=NULL,

    # ----------------
    # Outlier analysis
    ID="row.name", ID_size=0.60,
    MD_cut=0, out_cut=0, out_shape="circle", out_size=1,

    # -------------------------------------------------
    # Fit line, confidence interval, confidence ellipse
    fit=c("off", "loess", "lm", "ls", "null", "exp", "quad",
          "power", "log"),
    fit_power=1, fit_se=0.95,
    fit_color=getOption("fit_color"), fit_lwd=getOption("fit_lwd"),
    fit_new=NULL, plot_errors=FALSE, ellipse=0,
    ellipse_fill=getOption("ellipse_fill"),
    ellipse_color=getOption("ellipse_color"),
    ellipse_lwd=getOption("ellipse_lwd"),

    # -----------------------------------------------------------------------
    # Time series and forecasting, plot x values sequentially [xDate, y or Y]
    ts_unit=NULL, ts_ahead=0, ts_method=c("es", "lm"),
    ts_source=c("fable", "classic"), ts_agg=c("sum", "mean"),
    ts_NA=NULL, ts_format=NULL, ts_fitted=FALSE, ts_PI=.95, 
    ts_trend=NULL, ts_seasons=NULL, ts_error=NULL, 
    ts_alpha=NULL, ts_beta=NULL, ts_gamma=NULL, ts_new_x=NULL,
    ts_stack=FALSE, ts_area_fill="transparent", ts_area_split=0,
    ts_n_x_tics=NULL,
    # Run chart (indicate with .Index for the name of the x-variable)
    show_runs=FALSE, center_line=c("off", "mean", "median", "zero"),

    # -----------
    # Bubble plot [xCategorical, or xCategorical and yCategorical]
    radius=NULL, power=0.5, low_fill=NULL, hi_fill=NULL,

    # -----------------------------------------------------------
    # Large data sets, smoothing, contours and binning  [x and y]
    smooth_points=100, smooth_size=1,
    smooth_power=0.25, smooth_bins=128, hex_bins=30, hexbin_legend=TRUE,
    n_bins=1,
    contour_n=20, contour_nbins=50, contour_points=FALSE,
    contour_legend=FALSE,

    # -----------------------------
    # Bins for a frequency polygon
    bin=FALSE, bin_start=NULL, bin_width=NULL, bin_end=NULL,
    breaks="Sturges", cumulate=FALSE,


    # ----------------------
    # Axes labels and values
    # ----------------------

    # -----------------------
    # Axis labels and spacing
    xlab=NULL, ylab=NULL, main=NULL, sub=NULL,
    label_adjust=c(0,0), margin_adjust=c(0,0,0,0),  # top, right, bottom, left
    pad_x=c(0,0), pad_y=c(0,0),

    # ---------------------
    # Axis values specified
    scale_x=NULL, scale_y=NULL, origin_x=NULL, origin_y=NULL,

    # ---------------------
    # Axis values formatted
    rotate_x=getOption("rotate_x"), rotate_y=getOption("rotate_y"),
    offset=getOption("offset"),
    axis_fmt=c("K", ",", ".", ""), axis_x_prefix="", axis_y_prefix="",
    font_size=1,
    xy_ticks=TRUE, n_axis_x_skip=0, n_axis_y_skip=0, 

    # ------
    # legend
    legend_title=NULL,


    # -------------
    # Miscellaneous
    # -------------

    # ----------------------------------------------------
    # Add one or more objects, text, or geometric figures
    add=NULL, x1=NULL, y1=NULL, x2=NULL, y2=NULL,

    # ---------------------------------------------
    # Output: turn off, to PDF file, decimal digits
    quiet=getOption("quiet"), do_plot=TRUE,
    use_plotly=getOption("lessR.use_plotly"),
    pdf_file=NULL, width=6.5, height=6,
    digits_d=NULL,

    # -------------------------------------------------------------
    # Deprecated, to be removed in future versions
    smooth=FALSE,
    stat=c("mean", "sum", "sd", "deviation", "min", "median", "max"),
    stat_x=c("count", "proportion", "\%"),

    # ---------------------------------
    # Other
    eval_df=NULL, fun_call=NULL, \dots)
}

\arguments{
  \item{x}{The \emph{variable} plotted on the \code{x}-axis.
        The \strong{data values} are continuous, either
        cross-sectional or a time series. If \code{x} is sorted with equal
        intervals separating the values, or is a time series, then by default
       the points are plotted sequentially and connected with line segments.
        If named \code{.Index}, a run chart is generated from the corresponding
        \code{y} variable. Can specify multiple \code{x}-variables or multiple
        \code{y}-variables as vectors, but not both.}
  \item{y}{The continuous \emph{variable} plotted on the vertical
        \code{y}-axis.}
  \item{data}{Data frame that contains one or both of \code{x} and
        \code{y}. Default data frame is \code{d}. Specify \code{NULL} if
        the variables for the analysis are in the global environment instead.}
  \item{filter}{A logical expression or a vector of integers that specify the
        row numbers to retain, defining a subset of rows of the data frame to
        analyze.}\cr

  \item{by}{A \emph{grouping variable}, a categorical variable that provides
        separate group profiles of the primary numeric variables \code{x}
        and \code{y} on the \emph{same} plot.
        Only one \code{by} variable is permitted, as the resulting visual clutter
        compromises interpretability. Stratification by \code{by}
        applies only to a scatter plot, \code{form="scatter"}, not to the
        \code{"smooth"}, \code{"contour"}, and \code{"hexbin"} forms.}
  \item{facet}{One categorical variable, or a vector of two categorical
        variables, providing a separate plot of the primary
        variable(s) \code{x} and \code{y} for each level of the variable or
        combination of two levels. Stratification by \code{facet} applies to
        the \code{"scatter"}, \code{"smooth"}, \code{"contour"}, and
        \code{"hexbin"} forms, each panel sharing a common scale so that the
        panels are directly comparable.\cr
        When \code{x} (or \code{y}) is a vector of variables, the
        multi-series overlay is repeated across the panels, such as
        \code{XY(c(Pre, Post), Salary, facet=Gender)}: each panel displays
        the full overlay for one level of the \code{facet} variable.}
  \item{n_row}{Optional specification for the number of rows
        in the facet layout, a multi-panel display.
        Specify \code{n_col} or \code{n_row}, but not both.}
  \item{n_col}{Optional specification for the number of columns in the
        facet layout. Specify \code{n_col} or \code{n_row}, but not both.
        The default is \code{1}.}
  \item{aspect}{Aspect ratio (height/width) of the panels, applied only to the
       lattice facet forms: scatter and hexbin. The default \code{"fill"} expands
       each panel to occupy the available space (here \code{"fill"} refers to
       filling space, not to the \code{fill} color argument). Set to \code{1}
       for square panels, or \code{"xy"} to bank line slopes toward an effective
       45 degrees. The base-R contour and smooth facets size their panels
       automatically and ignore \code{aspect}.}\cr

  \item{form}{The plotted geometric form.
        The default is \code{"scatter"} for a scatter plot.
        To summarize the bivariate density for two numeric variables, set to
        \code{"smooth"} for a \strong{smoothed density plot},
        \code{"hexbin"} for a hexbin plot, or \code{"contour"} for a
        \strong{contour plot}.}\cr

  \item{theme}{Color theme for this analysis. Make persistent across analyses
        with \code{\link{style}}.}
  \item{fill}{Fill color for the points.
        Can also be set via the lessR function \code{\link{getColors}}
        to select from a variety of color palettes. For points, the default is
        \code{pt_fill}; for the area under a line chart, \code{violin_fill}.
        For a line chart, set to \code{"on"} to use the default color.}
  \item{color}{Border color of the points or line color for a line plot.
        Can be a vector to customize the color for each point or a color
        range such as \code{"blues"} (see \code{\link{getColors}}).
        Default is \code{pt_color} from the lessR \code{\link{style}} function.}
  \item{transparency}{Transparency factor of the fill color of each point.
        Default is \code{trans_pt_fill} from the lessR \code{\link{style}}
        function, which is 0.1 for points. Bubbles have a default
        transparency of 0.3.}\cr

  \item{enhance}{For a two-variable scatterplot, if \code{TRUE},
        automatically add the 0.95 data ellipse,
        labels for outliers beyond a Mahalanobis distance of 6 from the
        ellipse center, the least squares line for all data,
        the least squares line for the data excluding outliers, and
        horizontal and vertical lines representing the means of the two
        variables.}
  \item{means}{If one variable is categorical (factor) and the other is
       continuous, then if \code{TRUE} the group means are plotted in the
       scatterplot by default. Also applies to a 1-D scatterplot.}
  \item{pt_size}{When set to a constant, the scaling factor for
        \strong{standard points} (not bubbles) or for a line, with default
        of 1.0 for points and 2.0 for a line.
       Set to 0 to suppress plotting of points. If \code{ts_area_fill} is
       used for a line chart, then the default is 0. When set to a variable,
       activates a bubble plot, with the size of each bubble further determined
       by the value of \code{radius}. Applies to the standard two-variable
       scatterplot.}
  \item{pt_size_cut}{For a bubble plot in which bubble sizes are defined by a
       \code{pt_size} variable, controls whether and how many bubble labels are
       shown. If \code{1} (or \code{TRUE}), show the value of the sizing
       variable for selected bubbles in the center of the bubbles, except
       when the bubble is too small. If \code{0} (or \code{FALSE}), no values
       are displayed. If a number greater than 1, display labels only for the
       indicated number of values (e.g., the maximum and minimum when set
       to \code{2}). The color of the displayed text is set by
       \code{bubble_text} from the \code{\link{style}} function.}
  \item{pt_shape}{Plot character(s). The default value is \code{"circle"}, with
       both a default exterior color and filled interior, explicitly specified
       by \code{"color"} and \code{"fill"}.
       Other possible values with fillable interiors
       are \code{"circle"}, \code{"square"}, \code{"diamond"},
       \code{"triup"} (triangle up), and \code{"tridown"} (triangle down),
       all uppercase and lowercase letters, all digits, and most punctuation
       characters. The integers 0–25 as defined by the base R
       \code{\link{points}} function also apply.}
  \item{line_width}{Width of the line segments that connect adjacent points,
        such as in time series plots. Set to 0 to remove line segments.}
  \item{segments}{Designed for interaction plots of means: connects each pair of
        successive points with a line segment. Pass a data frame of means,
        such as from \code{\link{pivot}}. To turn off connecting line segments
        for sorted, equal-interval data, set to \code{FALSE}. Currently,
        does not apply to Trellis plots.}
  \item{segments_y}{For one \code{x}-variable, draw a line segment from the
        \code{y}-axis to each plotted point. For two \code{x}-variables, the
        line segments connect the two points.}
  \item{segments_x}{Draw a line segment from the \code{x}-axis for each
        plotted point.}\cr

  \item{sort}{Sort the values of \code{y} by the values of \code{x}.
        Default \code{"0"} retains the
        original order, \code{"-"} sorts descending, and \code{"+"} sorts
        ascending. If \code{x} is a vector of two variables,
        sort by their difference.}
  \item{jitter_x}{Randomly perturb the plotted points of
       a scatterplot horizontally within the limits of the specified value,
       or set to \code{NULL} to rely upon the computed default value.}
  \item{jitter_y}{Vertical jitter. Defaults to \code{0}. Same interpretation
        as \code{jitter_x}.}\cr

  \item{ID}{Name of a variable that provides the \strong{labels for selected
       plotted points for outlier identification}, row names of the data frame
       by default. To label all points, use the \code{add} parameter
       (see below).}
  \item{ID_size}{Size of the plotted labels.
        Modify label text color with the \code{\link{style}} function
        parameter \code{ID_color}.}
  \item{MD_cut}{Mahalanobis distance cutoff to define an outlier in a
       two-variable scatterplot.}
  \item{out_cut}{Count or proportion of plotted points to label, in order of their
       distance from the center (means) of the univariate distribution or 
       scatterplot, sorted from most to least extreme.
       For two-variable plots, distance from the center is based on Mahalanobis
       distance.}
  \item{out_shape}{Shape of outlier points in a two-variable scatterplot.
        Modify fill color from the current \code{theme} with
        \code{out_fill} and \code{out2_fill} in \code{\link{style}}.}
  \item{out_size}{Size of outlier points in a two-variable
        scatterplot.}\cr

  \item{fit}{Type of \strong{best fit line}. Default is \code{"off"}.
        Options include \code{"loess"} for a non-linear smooth,
        \code{"lm"} for a linear least squares model (with synonym
        \code{"ls"}),
        \code{"null"} for the null (intercept-only) model,
        \code{"exp"} for exponential growth or decay,
        \code{"log"} for a logarithmic model,
        \code{"power"} for a general power model in conjunction with
        \code{fit_power}, and \code{"quad"} for a quadratic (power 2)
        model. If potential outliers are identified according to
        \code{out_cut}, a second (dashed) fit line is displayed based on
        the data \emph{excluding} those outliers.}
  \item{fit_power}{Power that describes the response \code{y} as a power
       function of the predictor \code{x}, required when
       \code{fit="power"}. Optionally, and experimentally, may apply
       to \code{fit="exp"}.}
  \item{fit_se}{Confidence level for the error band displayed around the
       line of best fit. Default is 0.95 when a fit line is specified,
       but is turned off when \code{plot_errors=TRUE}.
       Can be a vector to display multiple confidence bands.
       Set to 0 to suppress error bands.}
  \item{fit_color}{Color of the fit line.}
  \item{fit_lwd}{Line width of the fit line.}
  \item{fit_new}{When \code{fit} is set to a fitted curve such as
       \code{"lm"} or \code{"quad"}, predicted values are computed at the
       \code{x}-values supplied here.}
  \item{plot_errors}{If \code{TRUE}, plot line segments joining each point to
        the regression line (\code{"loess"} or \code{"lm"}), illustrating the
        size of the residuals.}
  \item{ellipse}{Confidence level of a data ellipse for a scatterplot
        of one \code{x}-variable and one \code{y}-variable according to the
        contours of the corresponding bivariate normal density.
        Specify the confidence level(s) as a single number or a vector of
        values between 0 and 1 to plot one or more ellipses.
        Ellipses are not available in the interactive \code{plotly} version.
        For Trellis graphics, only the maximum level is used, with one ellipse
        per panel. Modify fill and border colors with the \code{\link{style}}
        parameters \code{ellipse_fill} and \code{ellipse_color}.}
   \item{ellipse_fill}{Fill color of the ellipse.}
   \item{ellipse_color}{Edge color of ellipse.}
   \item{ellipse_lwd}{Line width of the ellipse.}\cr

  \item{ts_unit}{Time unit for plotting \strong{time series data} when \code{x}
  is of type \code{Date}. Default is to infer the unit from the observed date
  spacing. Specify \code{ts_unit} to override the inferred unit and, when
  requested, aggregate to a coarser unit. Valid values are \code{"days"},
  \code{"weeks"}, \code{"months"}, \code{"quarters"}, \code{"years"}, and
  \code{"days7"} (daily data with a 7-day seasonal cycle).}
  \item{ts_ahead}{Number of \code{ts_unit} steps ahead of the last time period
        to forecast.}
  \item{ts_method}{Forecasting method. Default is \code{"es"} for exponential
       smoothing models. Alternatively, choose \code{"lm"} for a least squares
       linear regression model that accounts for seasonality.}
  \item{ts_source}{Source of forecasting functions. Default is \code{"fable"}
        for access to \code{ETS()} and \code{TSLM()} from the \pkg{fable}
        package and related functions from the \pkg{fpp3} ecosystem, or
        \code{"classic"} for base R forecasting functions.}
  \item{ts_agg}{Function used to aggregate over time according to
        \code{ts_unit}. Default is \code{"sum"} with an option for
        \code{"mean"}.}
  \item{ts_NA}{By default, missing \code{y} values (\code{NA}) are not plotted,
        leaving gaps. Alternatively, specify a value, usually 0, to replace
        \code{NA} and plot that value (e.g., 0) at the corresponding date.
        Forecasting with missing data is not supported.}
  \item{ts_format}{Optional format string for \code{as.Date()} describing
        the values of the date variable on the \code{x}-axis, needed if the
        function cannot infer the date format. For example, the character
        string \code{"09/01/2024"} can be described by
        \code{"\%m/\%d/\%Y"}. See \code{details} for more information.}
  \item{ts_fitted}{If \code{TRUE} and \code{ts_ahead} is used for forecasting,
        display for each data point the fitted value, level, trend, and
        seasonal component.}
  \item{ts_PI}{Prediction interval level about the forecasted values,
       with default of \code{0.95}.}
  \item{ts_trend}{Trend parameter. Default value is \code{NULL}, allowing the
       procedure to choose the specification that yields the best-fitting
       model for the data. Values \code{"A"} and \code{"M"} indicate additive
       and multiplicative models, respectively. Specify \code{"N"} to omit
       the trend component. See the forecasting documentation for valid
       combinations of trend, season, and error.}
  \item{ts_seasons}{Seasonality parameter. See \code{ts_trend}.}
  \item{ts_error}{Error parameter. See \code{ts_trend}.}
  \item{ts_alpha}{Exponential smoothing level parameter. Sets the value for
       \code{HoltWinters()}, and acts as a suggestion for
       \code{ETS()} in the \code{"fable"} framework.}
  \item{ts_beta}{Exponential smoothing trend parameter. See \code{ts_alpha}.}
  \item{ts_gamma}{Exponential smoothing seasonal parameter. See \code{ts_alpha}.}
  \item{ts_new_x}{A data frame of predictor variable names and new values for
       predictor variables used for model fitting and forecasting.
       The number of rows of new data values determines the number of future
       time periods for which forecasts are generated.
       Currently applies only to the default \code{"fable"} linear model
       for \code{ts_method="lm"}.}
  \item{ts_stack}{If \code{TRUE}, multiple time plots are stacked on each other,
        with \code{area} set to \code{TRUE} by default.}
  \item{ts_area_fill}{Fill under line segments, if present.
       If \code{ts_stack} is \code{TRUE}, the default is a gradient from the
       default color range (e.g., \code{"blues"}).
       If not specified, and \code{fill} is set with no plotted points and
       \code{ts_area_fill} is not specified, then \code{fill} generally
       controls the area under the line segments.}
  \item{ts_area_split}{Applies only to a Trellis plot activated with \code{facet}.
       Value of \code{y} that defines a reference line splitting the filled
       area under the time series line. Values of \code{y} below this threshold
       lie below the reference line; values above lie above the line.}
  \item{ts_n_x_tics}{Suggested number of ticks for dates on the \code{x}-axis,
       overriding the default of approximately seven ticks.}
  \item{show_runs}{If \code{TRUE}, display the individual runs in the run analysis.
        Also sets \code{run} to \code{TRUE}. Customize the color of the line
        segments with \code{segments_color} via \code{\link{style}}.}
  \item{center_line}{Plots a dashed line through the middle of a run chart.
        Values are \code{"off"}, \code{"mean"}, \code{"median"}, and
        \code{"zero"}, which specify that the center line goes through the
        mean, median, or zero, respectively. When not specified, a
        \code{"median"} center line is displayed if the values frequently
        vary about the mean, otherwise no center line.
        Currently not supported for Trellis plots.}\cr


  \item{radius}{Scaling factor of the bubbles in a \strong{bubble plot}, which
        sets the radius of the largest displayed bubble in inches. To
        activate bubble scaling, set \code{pt_size} to a third variable, or
        for categorical variables (factors), the bubble sizes represent
        frequencies.}
  \item{power}{Relative scaling of bubble sizes. The default value of 0.5
        scales bubbles so that the area of each bubble is proportional to
        the corresponding sizing variable. A value of 1 scales bubble radii
        directly by the sizing variable, increasing the size differences
        between values.}
  \item{low_fill}{For a categorical variable and the resulting bubble plot,
        or a matrix of such plots, sets the low end of a color gradient
        for bubble fill.}
  \item{hi_fill}{For a categorical variable and the resulting bubble plot,
        or a matrix of such plots, sets the high end of a color gradient
        for bubble fill.}\cr

  \item{smooth_points}{Number of points superimposed on the density plot in
        the areas of lowest density to help identify outliers, thereby
        controlling how dark the smoothed display becomes.}
  \item{smooth_size}{Size of points superimposed on the density plot.
        Default value is 1, resulting in very small points.}
  \item{smooth_power}{Exponent of the function that maps the density scale to
        the color scale. Smaller values than the default of 0.25 yield
        darker plots.}
  \item{smooth_bins}{Number of bins in each direction for the density
        estimation.}
  \item{hex_bins}{Number of bins in each direction for the hexbin plot.}
  \item{hexbin_legend}{If \code{TRUE}, the default, display the color key
        (legend) that maps fill colors to the binned counts on the right side
        of the hexbin plot. Set to \code{FALSE} to suppress the legend.}
  \item{n_bins}{Number of bins for a single numeric
       \code{x}-variable when visualizing the mean or median of a
       numeric \code{y}-variable for each bin. Points are plotted
       as bubbles, with bubble size proportional to the bin sample size,
       unless \code{pt_size} is specified as a constant. Default is 1
       (no binning).}
  \item{contour_n}{Number of contour levels in a contour plot, with
       default of 20.}
  \item{contour_nbins}{Number of bins constructed for each of \code{x} and
        \code{y}, forming the 2D grid from which densities are estimated.}
  \item{contour_points}{If \code{TRUE}, plot the original scatterplot points
        in a light gray with white borders, representing the data from which
        the contour curves are estimated. Color is not affected by other
        color settings, but point size can be changed with \code{pt_size}.
        Default size is 0.72.}
  \item{contour_legend}{If \code{TRUE}, display the color key (legend) that
        maps fill colors to density values on the right side of the contour
        plot. Default is \code{FALSE} (legend suppressed).}\cr

  \item{bin}{If \code{values="count"},  display the frequency distribution for 
       a frequency polygon.}
  \item{bin_start}{Optional starting value of the bins for a
        \strong{frequency polygon}.}
  \item{bin_width}{Optional specified bin width. Also sets
        \code{bin=TRUE}.}
  \item{bin_end}{Optional value that lies within the last bin, so the
        actual endpoint of the last bin may be larger than the specified
        value.}
  \item{breaks}{Method for calculating bins, or an explicit
        specification of the bins, such as via \code{\link{seq}} or other
        options provided by \code{\link{hist}}. Also sets
        \code{bin=TRUE}.}
  \item{cumulate}{If \code{TRUE}, display a cumulative frequency polygon.}\cr

  \item{xlab, ylab}{\strong{Axis labels} for the \code{x}- and \code{y}-axes.
       If not specified, labels default to the corresponding variable labels
       (if present), otherwise to the variable names. If \code{xy_ticks} is
       \code{FALSE}, no \code{ylab} is displayed. Customize these and related
       parameters with options such as \code{lab_color} in
       \code{\link{style}}.}
  \item{main}{Label for the plot title. If corresponding variable labels
       exist, the title is set by default from those labels.}
  \item{sub}{Subtitle for the graph, below \code{xlab}. Not yet implemented.}
  \item{label_adjust}{Two-element vector (x-axis label, y-axis label) that
       adjusts the positions of axis labels in approximate inches.
       Positive values move labels away from the plot edge.
       Not applicable to Trellis graphics.}
  \item{margin_adjust}{Four-element vector (top, right, bottom, left)
       that adjusts plot margins in approximate inches.
       Positive values move the corresponding margin away from the plot edge.
       Can be used with \code{offset} to move axis values into the expanded
       margin space. Not applicable to Trellis graphics.}
  \item{pad_x}{Proportion of padding added to the left and right sides of the
       \code{x}-axis. Values range from 0 to 1 for each of the two elements.
       If only one element is specified, it is applied to both sides.}
  \item{pad_y}{Proportion of padding added to the bottom and top sides of the
       \code{y}-axis. Values range from 0 to 1 for each of the two elements.
       If only one element is specified, it is applied to both sides.}\cr

  \item{scale_x}{If specified, a vector of three values that define the
        numeric \code{x}-axis: starting value, ending value, and number
        of intervals.}
  \item{scale_y}{If specified, a vector of three values that define the
        numeric \code{y}-axis: starting value, ending value, and number
        of intervals.}
  \item{origin_x}{Origin of the \code{x}-axis. Default is the minimum value
       of \code{x}, except for time series plots and when \code{stat}
       is set to \code{"count"} or a related option, in which case the
       origin defaults to 0.}
  \item{origin_y}{Origin of the \code{y}-axis. Default is the minimum value
       of \code{y}, except for time series plots and when \code{stat}
       is set to \code{"count"} or a related option, in which case the
       origin defaults to 0.}\cr

  \item{rotate_x}{\strong{Rotation in degrees of the axis value labels} on
        the \code{x}-axis, usually to accommodate longer labels,
        typically used with \code{offset}. If set to 90, labels are
        perpendicular to the axis and a different placement algorithm is
        used so that \code{offset} is not needed.}
  \item{rotate_y}{Rotation in degrees of the axis value labels on
        the \code{y}-axis, usually to accommodate longer labels,
        typically used with \code{offset}.}
  \item{offset}{Spacing between axis value labels and the axis. Default
        is 0.5. Larger values (e.g., 1.0) create additional space for
        labels, especially when rotated. Can be used with
        \code{margin_adjust} to create additional margin space for axis
        labels and values.}\cr
  \item{axis_fmt}{Numeric format of axis labels for both axes. Default
        rounds thousands to \code{"K"} (e.g., 100000 becomes 100K).
        Alternatives include \code{","} to insert commas in large numbers
        with a decimal point, \code{"."} to insert periods, or \code{""}
        to turn off formatting.}
  \item{axis_x_prefix}{Prefix for axis labels on the \code{x}-axis,
        such as \code{"$"}.}
  \item{axis_y_prefix}{Prefix for axis labels on the \code{y}-axis,
        such as \code{"$"}.}
  \item{font_size}{Multiplicative scaling factor applied to the font sizes
        of the title (\code{main_size}), axis labels (\code{lab_size}), and
        axis value text (\code{axis_size}) simultaneously, preserving their
        relative proportions. Default is \code{1} (no scaling).}
  \item{xy_ticks}{Flag indicating whether tick marks and associated
        \strong{value labels} on the axes are displayed. To rotate axis values,
        use \code{rotate_x}, \code{rotate_y}, and \code{offset} (see
        \code{\link{style}}).}
  \item{n_axis_x_skip}{Particularly useful for Trellis or facet plots with
        many labels on the \code{x}-axis. Specifies the spacing for skipping
        labels. A value of 0 includes all labels (default). A value of 1
        skips every other label, 2 includes every third label, etc.
        Also consider \code{rotate_x}.}
  \item{n_axis_y_skip}{Same as \code{n_axis_x_skip} but applies to the
        \code{y}-axis.}\cr

  \item{legend_title}{Title of the legend for a multiple-variable \code{x}
       or \code{y} plot.}\cr

  \item{add}{\strong{Overlay one or more objects}, text or geometric figures,
       on the plot. Possible values include any text (first argument) or
       \code{"text"}; \code{"labels"} to label each point with the row name;
       and geometric objects \code{"rect"} (rectangle), \code{"line"},
       \code{"arrow"}, \code{"v_line"} (vertical line), and
       \code{"h_line"} (horizontal line).
       The value \code{"means"} draws vertical and horizontal lines at the
       respective means. Does not apply to Trellis graphics.
       Customize with parameters such as \code{add_fill} and \code{add_color}
       via \code{\link{style}}.}
  \item{x1}{First x-coordinate for each overlaid object; may be
       \code{"mean_x"}. Not used for \code{"h_line"}.}
  \item{y1}{First y-coordinate for each overlaid object; may be
       \code{"mean_y"}. Not used for \code{"v_line"}.}
  \item{x2}{Second x-coordinate for each object; may be \code{"mean_x"}.
       Used only for \code{"rect"}, \code{"line"}, and \code{"arrow"}.}
  \item{y2}{Second y-coordinate for each object; may be \code{"mean_y"}.
       Used only for \code{"rect"}, \code{"line"}, and \code{"arrow"}.}\cr

  \item{quiet}{If \code{TRUE}, suppress text output. Can change the system
       default with \code{\link{style}}.}
  \item{do_plot}{If \code{TRUE} (default), generate the plot.}
  \item{use_plotly}{If \code{TRUE} (default), draw a \code{plotly} interactive
        plot in the RStudio \code{Viewer} window in addition to the static plot
        in the \code{Plots} window. Not all options are available in the
        interactive version, but key options are supported.}
  \item{pdf_file}{If specified, direct PDF graphics to the given file name.}
  \item{width}{Width of the plot window in inches, default 5 except within
        RStudio, where the default maintains an approximately square plotting
        area.}
  \item{height}{Height of the plot window in inches, default 4.5 except for
        1-D scatterplots and when running in RStudio.}
  \item{digits_d}{Number of significant digits for each displayed summary
        statistic.}\cr

  \item{smooth}{\emph{Deprecated}. Now use parameter \code{form}.}
  \item{stat}{\emph{Deprecated}. Functionality moved to \code{Chart()}.
       Apply a \strong{specified aggregation} such as \code{"mean"} to the
       numerical \code{y} variable at each level of a categorical \code{x}
       variable. The resulting dot plot (Cleveland plot) is analogous to a
       bar chart but emphasizes position along a common scale.}
  \item{stat_x}{\emph{Deprecated}. If no \code{y} variable is specified,
        constructs a frequency
        polygon for \code{x} with access to \code{bin_width}. Either use the
        default \code{"count"} for each bin or \code{"proportion"}, also
        indicated by \code{\%}.}\cr

  \item{eval_df}{If \code{TRUE}, checks that variables exist in the supplied
        data frame. Default of \code{NULL} determines the setting
        automatically. Set to \code{FALSE} in Shiny or pipe workflows.}
  \item{fun_call}{Function call. Used with \pkg{knitr} to pass the function
        call when obtained from the abbreviated helper \code{sp}.}\cr

  \item{\dots}{Other parameters for non-Trellis graphics as recognized by
      base R functions \code{\link{plot}} and \code{\link{par}}, including
      \code{cex.main} for the size of the title,
      \code{col.main} for the color of the title,
      and \code{sub} and \code{col.sub} for a subtitle and its color.}
}


\details{
VARIABLES and TRELLIS PLOTS

There is at least one primary variable, \code{x}, which defines the horizontal
\code{x}-axis. A second primary variable, \code{y}, defines the vertical
\code{y}-axis. Either \code{x} or \code{y} (but not both simultaneously) may be
a vector of variables. The simplest usage—single \code{x} and \code{y}—produces
a single scatterplot on one panel. With \code{form="scatter"} this is a
standard point plot; alternative values such as \code{"smooth"} and
\code{"contour"} invoke 2-D kernel density and contour displays, respectively.

For numeric primary variables, multiple plots can appear on a single panel in
two ways. First, by defining groups with the \code{by} argument:
\code{by} identifies a categorical grouping variable, and a separate
scatterplot layer is drawn for each of its levels. Group levels are
distinguished by color and/or shape. By default, both colors and shapes vary
across groups, which also aids readability for color-blind viewers; for two
groups, a common pattern is a filled symbol for one group and a point
with transparent interior for the other.

Second, multiple numeric \code{x}-variables or multiple \code{y}-variables can
be supplied as a vector, which produces multiple series on the same panel. This
is commonly used for time series overlays and multi-series line plots.

Trellis graphics (facets), from Deepayan Sarkar's (2009) \code{lattice}
package, may also be used. A variable specified with \code{facet} is a
conditioning variable. A single \code{facet} variable produces one panel for
each of its levels; a length-two vector of facet variables produces one panel
for each cross-classified combination of their levels. Within each panel,
\code{x} and \code{y} are plotted as usual, and an additional grouping variable
specified with \code{by} may be applied to all panels. When \code{x} has at
most 1000 unique values, XY() can provide a brief diagnostic of the maximum
number of repeated values for each level of \code{facet}.

A vector of variables passed to \code{x} (or \code{y}) combines with
\code{facet}: the multi-series overlay is repeated across the panels, each
panel displaying the full overlay for one level (or combination of levels)
of the \code{facet} variable(s), with all panels on a common scale for
direct comparison. Because the multiple series already occupy the color
(series) dimension of the plot, \code{by} does not apply when \code{x} or
\code{y} is a vector.

Control the panel dimensions and the overall size of the Trellis display with
\code{width} and \code{height} for the graphics device, \code{n_row} and
\code{n_col} for the number of panels in each direction, and \code{aspect} for
the panel height-to-width ratio. The plot window is the active graphics device
(e.g., the standard R plotting window, RStudio \code{Plots} pane, or a pdf file
when \code{pdf_file} is specified).\cr

CATEGORICAL VARIABLES

Categorical variables have relatively few unique values and are recommended
to be often coded as factors. However, categorical variables may also be coded numerically, such as Likert responses from 1 to 5. The structuring arguments \code{by} and \code{facet} apply when at least one of \code{x} or \code{y} is numeric, but that numeric variable may represent either a truly continuous scale or a discrete Likert-type scale.

A continuous variable, including time, models an underlying continuous scale,
even though all continuous variables are necessarily measured at discrete
precision. The distinction from a categorical variable is the scale that the
values represent, not the finiteness of the recorded values. A date-valued
\code{x} is therefore a continuous variable, which is why the time-series
display of \code{XY()} requires no qualification beyond continuous \code{x}.

Scatterplots of Likert-type data can be challenging because the number of
possible joint values is small. For two five-point scales there are only 25
possible combinations, so many points overlap at the same coordinates. For such
situations, jittering, or dot/mean plots (using \code{stat}) may
provide clearer displays.

The relationship between two categorical variables is instead displayed with
\code{\link{Chart}}, specifying \code{form="bubble"} and a \code{by} variable,
which sizes each bubble by the joint frequency of the two categories.\cr

DATA

The default input data frame is \code{d}. Another data frame can be specified
with the \code{data} argument. Regardless of the name of the data frame,
variables can be referenced directly by name—no need to attach the data frame
or use \code{d$name}. Referenced variables may live in the data frame, the
global environment, or both. If \code{x} is a time series of class \code{ts}, first extract the date and value components with \code{\link{tsExtract}}, then pass them to \code{XY}.

The plotted values can be the raw data themselves, or summaries derived from
them. With a single numeric variable, counts or proportions can be plotted on
the \code{y}-axis, optionally after binning \code{x}. For a categorical
\code{x}-variable paired with a continuous \code{y}-variable, summary
statistics such as means can be plotted at each level of \code{x}. When
\code{x} is continuous and binning is desired, XY() uses the same binning
parameters as \code{\link{X}}, such as \code{bin_width}, to override
defaults. The \code{stat} parameter controls what is plotted (e.g.,
\code{"data"}, \code{"mean"}, \code{"median"}). By default, connecting line
segments are drawn, yielding a frequency polygon. Turn off line segments by
setting \code{line_width=0}.

The \code{filter} parameter subsets rows (cases) of the input data frame
according to a logical expression or a vector of integers specifying row
numbers to retain. Use standard R logical operators as described in
\code{\link{Logic}}—for example, \code{&} (and), \code{|} (or), and \code{!}
(not)—and relational operators as described in \code{\link{Comparison}} such as
\code{==} (equality), \code{!=} (not equal), and \code{>} (greater than). To
specify rows directly, create an integer vector using standard R syntax. See
\code{Examples}.\cr

VALUE LABELS\cr
\emph{Deprecated. Use \code{factor()} instead.}  

The \code{value_labels} option can override the axis tick labels with
user-supplied values. This is particularly useful for Likert-style data coded
as integers: for example, a data value \code{0} can be displayed as
\code{"Strongly Disagree"}. These labels apply to integer categorical variables
and to factor variables. Any spaces in a label are translated into line breaks
to improve readability.

In current workflows, the recommended approach is to define factors with the
desired labels directly, typically via \code{\link{factors}}, which allows
convenient creation of labeled factors for one or more variables in a single
statement.\cr

VARIABLE LABELS

Base R does not natively support variable labels, but lessR stores labels in
the data frame alongside the variables, typically created by
\code{\link{Read}} or \code{\link{VariableLabels}}. When variable labels
exist, XY() uses them by default for axis labels and in text output. Otherwise,
the variable names are used.\cr

TWO VARIABLE PLOT

With two variables specified, XY() behaves as follows. If the values of
\code{x} are unsorted, have unequal intervals, or there is missing data in
either variable, a standard scatterplot is produced (for \code{form =
"scatter"}). When \code{x} is sorted with equal intervals and there are no
missing values, the default display connects adjacent points with line
segments, yielding a function or time-series style plot.

Supplying multiple continuous \code{x}-variables against a single \code{y}, or
vice versa, produces multiple series on the same graph. The points for the
second series reuse the first series' color but with transparent fill; for more
series, additional colors from the current theme are used.\cr

SCATTERPLOT MATRIX

If \code{x} and \code{y} specify the same vector of continuous variables,
as in \code{XY(c(Years, Pre, Post), c(Years, Pre, Post))}, XY() generates
a scatterplot matrix. To specify the variable list once, store it as a
data frame subset and reference it for both \code{x} and \code{y}, as in
\code{vec <- d[, c("Years", "Pre", "Post")]} followed by
\code{XY(vec, vec, data=NULL)}.
The matrix adopts the current color theme.
Individual colors (e.g., \code{fill}, \code{color}) can be overridden. The
lower triangle shows the pairwise scatterplots, and the upper triangle shows
the corresponding correlation coefficients. By default a non-linear loess fit
line is added to each scatterplot; the \code{fit} parameter can be used to
request a linear least squares line instead, along with \code{fit_color} to set
its color.\cr

SIZE VARIABLE\cr
Specifying a numeric \code{pt_size} variable activates a bubble plot in which the
area of each bubble is determined by the corresponding value of \code{pt_size}
(modified by \code{radius} and \code{power}).

Shapes vary across groups by default. To set shapes explicitly, use
\code{pt_shape} and provide a vector of values (e.g., created with
\code{\link{c}}), one shape per level of the grouping variable in \code{by},
or set \code{pt_shape} to a single value (e.g., \code{"circle"}) to use the same
shape for all groups. To control colors, use \code{fill} with values for each
\code{by} level.

Beyond the named shapes such as \code{"circle"}, any single character (letters,
digits, \code{"+"}, \code{"*"}, \code{"#"}) may be used as a plotting symbol.
Within a single specification, either use standard named shapes or single
characters, but not both.\cr

SCATTERPLOT ELLIPSE

For a scatterplot of two numeric variables, the \code{ellipse} argument
requests one or more data ellipses, based on the contours of the corresponding
bivariate normal density. For a single \code{x}- and \code{y}-variable pair,
setting \code{ellipse} to a numeric value between 0 and 1 (e.g., 0.95) draws
the corresponding probability contour. A vector of values produces multiple
ellipses. XY() expands the axes as needed so that ellipses extending beyond the
range of the data remain fully visible. For Trellis graphics, only the largest
ellipse level is used (one ellipse per panel). Ellipse fill and border colors
are controlled via \code{ellipse_fill} and \code{ellipse_color} in
\code{\link{style}}.\cr

TIME CHARTS

See \url{https://web.pdx.edu/~gerbing/lessR/examples/Time.html} for additional
examples and explanation.


\subsection{Run Chart}{

When \code{x} is the special variable \code{.Index}, XY() produces a run chart
of \code{y}. The \code{y}-values are plotted against their index positions
(1, 2, …), and run-chart diagnostics such as center lines and runs analysis can
be displayed via the corresponding arguments.
}

\subsection{Time Series Defined with Dates}{

If \code{x} is of type \code{Date} or an R time-series object, XY() produces a
time series plot for each specified variable. Time-series data can be supplied
in \dQuote{long} format (a single column of values plus a date column) or in
\dQuote{wide} format (multiple time-series columns sharing a date index). XY()
will attempt to convert character string date values (e.g.,
\code{"08/18/1952"}) to \code{Date} via \code{as.Date()}, using default date
formats when possible.

XY() makes a reasonable attempt to decode common date formats, but some formats
(e.g., those with month names rather than numbers) may require an explicit
format string via \code{ts_format}. If the default conversion fails or is
ambiguous, specify the correct format using examples such as those in the
table below. Note that \code{ts_format} can always be provided for explicit
specification of the date format.\cr

\tabular{ll}{
Example Date \tab Format\cr
--------------------------- \tab ----------------- \cr
\code{"2022-09-01"} \tab \code{"\%Y-\%m-\%d"}\cr
\code{"2022/9/1"} \tab \code{"\%Y/\%m/\%d"}\cr
\code{"2022.09.01"} \tab \code{"\%Y.\%m.\%d"}\cr
\code{"09/01/2022"} \tab \code{"\%m/\%d/\%Y"}\cr
\code{"9/1/22"} \tab \code{"\%m/\%d/\%y"}\cr
\code{"September 1, 2022"} \tab \code{"\%B \%d, \%Y"}\cr
\code{"Sep 1, 2022"} \tab \code{"\%b \%d, \%Y"}\cr
\code{"20220901"} \tab \code{"\%Y\%m\%d"}\cr
--------------------------- \tab ----------------- \cr
}

XY() also converts character-string dates such as \code{"2024 Aug"} and
\code{"2024 Q1"}, interpreting three-letter month abbreviations and quarter
codes \code{Q1}--\code{Q4}.

\strong{Time unit and aggregation.}
The \code{ts_unit} argument controls the time unit used for plotting and, when
specified, can also be used to aggregate the series to a coarser time unit. By
default, XY() attempts to infer a regular time unit from the observed spacing
of the dates (see \sQuote{Detecting the Regularity of Dates}). You may specify
\code{ts_unit} to override the inferred unit, including treating irregular
dates as a regular unit for aggregation (for example, \code{ts_unit="weeks"}).
The special value \code{"days7"} retains daily observations but evaluates
seasonality on a 7-day cycle.

When aggregation is requested, the date index is aggregated with
\code{endpoints()} and \code{period.apply()} from the \code{xts} package. The
aggregation function is specified with \code{ts_agg}, default \code{"sum"},
with \code{"mean"} as a common alternative.
}

\subsection{Detecting the Regularity of Dates (ts_unit)}{

For time series operations, \pkg{lessR} attempts to infer the regularity of a
date variable from the observed sequence of dates. The inferred unit is
returned internally as \code{tu_exist} and is one of \code{"days"},
\code{"weeks"}, \code{"years"}, \code{"quarters"}, \code{"months"}, or
\code{"unknown"}.

The decision rules are:

\enumerate{

\item \strong{Pre-processing.}
Dates are sorted and reduced to unique values. When a grouping variable is
present, regularity is evaluated from the first level only (assuming dates are
already time-sorted within that level). Day gaps are computed as positive
differences between successive dates.

\item \strong{Trivial / short series.}
If there are fewer than two dates, or if no positive gaps are available, the
unit is set to \code{"days"}.

\item \strong{Fine units (gap-based).}
Let \code{gap} be the median of the positive day gaps (median is robust to
occasional missing dates).

\itemize{
  \item If \code{gap == 1}, then \code{tu_exist="days"}.
  \item If \code{gap == 7}, then the series is a \emph{candidate} weekly series.
  The gap pattern is further examined to distinguish a regular weekly series
  (primarily 7-day gaps, with only occasional longer gaps) from an irregular
  reporting schedule (for example, many 14-day gaps). If judged sufficiently
  weekly, then \code{tu_exist="weeks"}; otherwise \code{tu_exist="unknown"}.
}

\item \strong{Coarse units (calendar-based).}
If the unit is still \code{"unknown"} after the fine-unit checks, the dates are
examined for calendar structure. Let \code{year}, \code{month}, and \code{day}
denote the corresponding calendar fields.

\itemize{

  \item \strong{Years.}
  If there is at most one observation per year and all observations share the
  same month and day-of-month (for example, January 1 each year), then
  \code{tu_exist="years"}. Missing years are permitted.

  \item \strong{Quarters.}
  If there is at most one observation per calendar quarter (unique
  year--quarter combinations) \emph{and} the median day gap between
  observations falls in the range 60--122 days, then
  the existing time unit is deemed as "quarters"}. 
  The reporting month and day-of-month may
  vary across quarters, and missing quarters are permitted. The gap range
  excludes sparse or irregular series that happen to have at most one
  observation per quarter by chance.

  \item \strong{Months.}
If the time variable is a Date but the observations occur exactly once per calendar month with no duplicates within a month and the sequence of months is regular (missing months become explicit NAs if present), then lessR treats the series as monthly and converts the index accordingly.


  \item \strong{Missing periods.}
  When a regular unit is accepted (\code{"weeks"}, \code{"years"},
  \code{"quarters"}, or \code{"months"}), a flag \code{has_missing_periods} is set
  to \code{TRUE} if the sequence of inferred periods contains gaps (for example,
  a 14-day gap in an otherwise weekly series, or a missing month in an otherwise
  monthly series). If the series is classified as \code{"unknown"},
  \code{has_missing_periods} is not used.
  }
}

If the user explicitly specifies \code{ts_unit}, that value is used for
aggregation and modeling, overriding the inferred unit. In particular, a
user-specified \code{ts_unit="months"} may treat one observation per month as
monthly even if the reporting day varies across months, and a user-specified
\code{ts_unit="weeks"} may treat dates as weekly even if the inferred
regularity is \code{"unknown"}.

\subsection{Missing Data}{

For missing data, if a date is present but the corresponding \code{y}-value is
\code{NA}, the line is broken at that point (no segment is drawn). If both the
date and value are absent (the entire row is missing), the line connects the
nearest observed dates, spanning the gap in calendar time but skipping the
missing tick label. For example, if "2021-01-07" and "2021-01-09" are present
but "2021-01-08" is absent, the plot includes points for the 7th and 9th
connected by a line; the 8th does not appear on the axis.
}

\subsection{Forecasting}{

Forecasting is activated by setting \code{ts_ahead} to a positive integer. The
trend, seasonal, and error components for exponential smoothing and regression
models follow the \code{fable} conventions and are controlled by
\code{ts_trend}, \code{ts_seasons}, and \code{ts_error}. XY() supports four
forecasting engines: \code{ETS()} and \code{TSLM()} from \code{fable} via
\code{ts_source="fable"}, and classic \code{HoltWinters()} and regression
decomposition (\code{stl()} + \code{lm()}) via \code{ts_source="classic"}.
Multiplicative components require positive data. Additive trend is linear,
while multiplicative trend corresponds to exponential growth or decay; additive
and multiplicative seasonality scale the seasonal pattern differently as the
series level changes.

Exponential smoothing via \code{ETS()} (the default when
\code{ts_source="fable"}) generally provides flexible model specification
and often superior predictive performance compared to classic Holt–Winters.
For regression with seasonality, \code{TSLM()} and the \code{stl()}+\code{lm()}
approach both rely on least squares but handle seasonal structure differently.
Setting \code{ts_fitted=TRUE} provides fitted values and decomposed trend and
seasonal components for inspection.\cr
}


2-D KERNEL DENSITY

Set \code{form="smooth"} to invoke \code{\link{smoothScatter}} and display a
2-D kernel density estimate for large data sets. The display respects the
current theme. The \code{smooth_points} argument controls how many points from
low-density regions are superimposed, \code{smooth_bins} sets the number of
bins in each direction for density estimation, and \code{smooth_power}
controls the transformation from density scale to color scale. Larger
\code{smooth_power} values reduce saturation in low-density regions. These
arguments map directly to \code{nrpoints}, \code{nbin}, and
\code{transformation} in \code{\link{smoothScatter}}. Grid lines are disabled
by default for smooth density plots, but can be re-enabled via the appropriate
styling options (e.g., \code{grid_color} in \code{\link{style}}).

Alternatively, set \code{form="contour"} to plot contour lines of the
estimated bivariate density, with the level resolution controlled by
\code{contour_n} and \code{contour_nbins}.

Each of the \code{"smooth"}, \code{"contour"}, and \code{"hexbin"} forms also
supports \code{facet} for coordinated small multiples, and every panel shares a
common scale so the panels are directly comparable. Contour and smooth panels
share a common kernel-density grid, bandwidth, and set of color levels;
hexbin panels share a single count legend. Faceted contour and smooth plots are
drawn as a base-R panel grid, whereas faceted hexbin plots use the native
paneling of the \code{hexbin} package. So the density can be compared across
panels, a faceted smooth plot estimates the density with
\code{\link[MASS]{kde2d}} rather than with \code{\link{smoothScatter}}, so its
appearance differs slightly from the corresponding single, unfaceted plot.\cr

COLORS

A global color theme for \code{XY()} and other lessR graphics can be set with
\code{\link{style}} (e.g., \code{style(theme="lightbronze")}). The default
theme is \code{"lightbronze"}. A grayscale theme is available via
\code{"gray"}, and other themes (e.g., \code{"sienna"}, \code{"darkred"}) are
described in \code{\link{style}}. The \code{sub_theme="black"} option yields
a black background with partially transparent plotted colors.

Individual graphical elements (points, lines, panels, grid lines, etc.) can be
customized with additional \code{\link{style}} arguments, such as
\code{panel_fill}. For a subtle warm background, try
\code{panel_fill="snow"}; very light grays such as
\code{"gray99"} or \code{"gray97"} provide a neutral tone.  

For many color options, the value \code{"off"} is equivalent to
\code{"transparent"}, removing the corresponding fill or border.

See \code{\link{showColors}} for a display of all named R colors and their RGB
values.\cr

ANNOTATIONS

The \code{add} argument and its related coordinates (\code{x1}, \code{y1},
\code{x2}, \code{y2}) annotate the plot with text and geometric objects. Each
object type requires a specific set of coordinates, summarized below.
\code{x}-coordinates may take the special value \code{"mean_x"} and
\code{y}-coordinates may take \code{"mean_y"}.\cr

\tabular{lll}{
Value \tab Object \tab Required Coordinates\cr
----------- \tab ------------------- \tab -----------------------\cr
\code{"text"} \tab text \tab x1, y1\cr
\code{"point"} \tab point \tab x1, y1\cr
\code{"rect"} \tab rectangle \tab x1, y1, x2, y2\cr
\code{"line"} \tab line segment \tab x1, y1, x2, y2\cr
\code{"arrow"} \tab arrow \tab x1, y1, x2, y2\cr
\code{"v_line"} \tab vertical line  \tab x1\cr
\code{"h_line"} \tab horizontal line  \tab y1\cr
\code{"means"} \tab horizontal and vertical lines at the means \tab \cr
----------- \tab ------------------- \tab -----------------------\cr
}

The value of \code{add} specifies the object type. For a single object, provide
one value and its required coordinates. For multiple placements of the same
object, supply coordinate vectors. For multiple different objects, supply a
vector of \code{add} values and, for each coordinate argument (\code{x1},
\code{y1}, \code{x2}, \code{y2}), a vector whose elements correspond to the
sequence of objects in \code{add}.

Styling options such as \code{add_color}, \code{add_fill}, and transparency
may also be given as vectors, allowing different objects to have different
colors or other properties.\cr

PDF OUTPUT

To obtain pdf output, set \code{pdf_file} to a file name, optionally with
\code{width} and \code{height} to control device size. The pdf is written to
the current working directory, which can be explicitly set with
\code{\link{setwd}}.\cr

ADDITIONAL OPTIONS

Many commonly used graphical parameters from the base \code{R} function
\code{\link{plot}} are passed through by XY(), including:

\describe{
  \item{cex.main, col.lab, font.sub, etc.}{Settings for main/sub-titles and axis
        annotation; see \code{\link{title}} and \code{\link{par}}.}
  \item{main}{Main title of the graph; see \code{\link{title}}.}
  \item{xlim}{Limits of the \code{x}-axis, expressed as \code{c(x1, x2)}. Note
        that \code{x1 > x2} is allowed and produces a reversed axis.}
  \item{ylim}{Limits of the \code{y}-axis.}
}

VARIABLES AND EXPRESSIONS

A referenced variable in \code{XY} is by default a variable name (or
vector of variable names), resolved from the referenced data frame
(e.g., the default \code{d}) or, with \code{data=NULL}, from the user's
workspace (global environment). A vector of variable names retains its
column-selection meaning, as in the scatterplot matrix
\code{XY(c(Years, Pre, Post), c(Years, Pre, Post))}.

The variable arguments \code{x}, \code{y}, \code{by}, and \code{facet}
also accept expressions, evaluated first against the columns of the data
frame, then against the user's workspace. The expression text serves as
the variable label. For example:\cr

\preformatted{
    > XY(rnorm(50), rnorm(50))   # expressions, no data frame needed
    > XY(Years, log(Salary))     # Years, Salary resolved from d
    > XY(Years, Salary, by=cut(Pre, 2))  # expression as by variable}

An expression that references a column of the data frame must evaluate
to one value per row of the data frame.

For a scatterplot matrix, store the variable list once as a data frame
subset and reference it for both \code{x} and \code{y}:\cr

\preformatted{
    > vec <- d[, c("Years", "Pre", "Post")]
    > XY(vec, vec, data=NULL)    # same matrix as the c() form above}
}


\value{
The output may be assigned to an \code{R} object; otherwise it is printed directly
to the console. Each component appears only when the corresponding analytic option
is activated. For example, outlier identification must be enabled (e.g., via
\code{MD_cut}) for \code{out_outliers} to be included in the output.

To save the results, assign the output to an object, such as  
\code{p <- XY(Years, Salary)}.  
Use \code{names(p)} to view the available components, and access any one by
prefixing with \code{p$}, for example \code{p$out_stats}.  
Output can be viewed interactively at the console or inserted into R~Markdown
documents for reproducible reporting.

READABLE OUTPUT

\code{out_stats}: Correlational analysis.\cr
\code{out_outliers}: Mahalanobis Distance values for detected outliers.\cr
\code{out_frcst}: Forecasted values.\cr
\code{out_fitted}: Fitted values for the observed data.\cr
\code{out_coefs}: Linear and seasonal coefficients from forecasting models.\cr
\code{out_smooth}: Smoothing parameters from exponential smoothing models.\cr
\code{out_bubble}: Bubble-plot settings, including \code{radius} and \code{power}.\cr
\code{out_reg}: Regression statistics produced when \code{fit} is specified.\cr

STATISTICS

\code{outliers}: Row numbers corresponding to detected outliers.\cr
}


\references{
Murdoch, D, and  Chow, E. D. (2013).  \code{ellipse} function from the \code{ellipse} package.

Gerbing, D. W. (2023). R Data Analysis without Programming, 2nd edition, Chapter 10, NY: Routledge.

Gerbing, D. W. (2020). R Visualizations: Derive Meaning from Data, Chapter 5, NY: CRC Press.

Gerbing, D. W. (2021). Enhancement of the Command-Line Environment for use in the Introductory Statistics Course and Beyond, \emph{Journal of Statistics and Data Science Education}, 29(3), 251-266, https://www.tandfonline.com/doi/abs/10.1080/26939169.2021.1999871.

Hyndman, R. J., & Athanasopoulos, G. (2021). \emph{Forecasting: Principles and Practice} (3rd ed.). Melbourne, Australia: OTexts. Retrieved from https://otexts.com/fpp3/

Sarkar, Deepayan (2008) Lattice: Multivariate Data Visualization with R, Springer. http://lmdvr.r-forge.r-project.org/

Sievert, C. (2020). \emph{Interactive Web-Based Data Visualization with R, plotly, and shiny}. Chapman and Hall/CRC. URL: \url{https://plotly.com/r/}
}

\author{David W. Gerbing (Portland State University; \email{gerbing@pdx.edu})}

\seealso{\code{\link{X}}, \code{\link{Chart}}, \code{\link{style}},
\code{\link{tsExtract}}.
}


\examples{
# read the data
d <- rd("Employee", quiet=TRUE)
d <- d[.(random(0.6)),]  # less computationally intensive
dd=d

#---------------------------------------------------
# traditional scatterplot with two numeric variables
#---------------------------------------------------

# scatterplot with all defaults
XY(Years, Salary)
# or use Plot in place of XY, the older method

# an expression as a variable, evaluated against the data frame,
#   with the expression text as the variable label
XY(Years, log(Salary))

XY(Years, Salary, by=Gender, pt_size=2, fit="lm",
     fill=c(M="olivedrab3", W="gold1"),
     color=c(M="darkgreen", W="gold4"))

# maximum information, minimum input: scatterplot +
#  means, outliers, ellipse, least-squares lines with and w/o outliers
XY(Years, Salary, enhance=TRUE)

# extend x and y axes
XY(Years, Salary, scale_x=c(-10, 35, 10), scale_y=c(0,200000,10))

XY(Years, Salary, add="Hi", x1=c(12, 16, 18), y1=c(80000, 100000, 60000))

d <- factors(Gender, levels=c("M", "W"))
XY(Years, Salary, facet=Gender)
d <- dd

\donttest{

# just males employed more than 5 years
XY(Years, Salary, filter=(Gender=="M" & Years > 5))

# plot 0.95 data ellipse with the points identified that represent
#   outliers defined by a Mahalanobis Distance larger than 6
# save outliers into R object out
d[1, "Salary"] <- 200000
out <- XY(Years, Salary, ellipse=0.95, MD_cut=6)

# new shape and point size, no grid or background color
# then put style back to default
style(panel_fill="powderblue", grid_color="powderblue")
XY(Years, Salary, pt_size=2, pt_shape="diamond")
style()

# translucent data ellipses without points or edges
#  show the idealized joint distribution for bivariate normality
style(ellipse_color="off")
XY(Years, Salary, pt_size=0, ellipse=seq(.1,.9,.10))
style()

# bubble plot with size determined by the value of Pre
# display the value for the bubbles with values of  min, median and max
XY(Years, Salary, pt_size=Pre, pt_size_cut=3)

# variables in a data frame not the default d
# plot 0.6 and 0.9 data ellipses with partially transparent points
# change color theme to gold with black background
style("gold", sub_theme="black")
XY(eruptions, waiting, transparency=.5, ellipse=seq(.6,.9), data=faithful)

# scatterplot with two x-variables, plotted against Salary
# define a new style, then back to default
style(window_fill=rgb(247,242,230, maxColorValue=255),
  panel_fill="off", panel_color="off", pt_fill="black", transparency=0,
  lab_color="black", axis_text_color="black",
  axis_y_color="off", grid_x_color="off", grid_y_color="black",
  grid_lty="dotted", grid_lwd=1)
XY(c(Pre, Post), Salary)
style()

# increase span (smoothing) of the loess fit
#   from the default of 0.75 to 1.25
# display confidence intervals about best-fit line at
#   0.95 confidence level
XY(Years, Salary, fit="loess", span=1.25)

# 2-D kernel density (more useful for larger sample sizes)
XY(Years, Salary, form="smooth")
}

#------------------------------------------------------
# scatterplot matrix from a vector of numeric variables
#------------------------------------------------------

# with least squares fit line
XY(c(Salary, Years, Pre), c(Salary, Years, Pre), fit="lm")

# same matrix from a stored variable list, a data frame subset
vec <- d[, c("Salary", "Years", "Pre")]
XY(vec, vec, data=NULL)


#--------------------------------------------------------------
# Trellis graphics and by for groups with two numeric variables
#--------------------------------------------------------------

# Trellis plot with condition on 1-variable
# optionally re-order default alphabetical R ordering by converting
#   to a factor with lessR factors (which also does multiple variables)
# always save to the full data frame with factors
d <- factors(Gender, levels=c("M", "W"))
XY(Years, Salary, facet=Gender)
d <- Read("Employee", quiet=TRUE)

\donttest{

# all three by (categorical) variables
XY(Years, Salary, facet=c(Dept, Gender), by=Plan, n_axis_y_skip=1)

# vary both shape and color with a least-squares fit line for each group
style(color=c("darkgreen", "brown"))
XY(Years, Salary, facet=Gender, fit="lm", pt_shape=c("W","M"), pt_size=.8)
style("gray")

# compare the men and women Salary according to Years worked
#   with an ellipse for each group
XY(Years, Salary, by=Gender, ellipse=.50)
}


#--------------------------------------------------------------
# facet the bivariate density displays: contour, smooth, hexbin
#   each panel shares a common scale, so panels are comparable
#--------------------------------------------------------------

\donttest{
XY(Years, Salary, form="contour", facet=Gender)
XY(Years, Salary, form="smooth", facet=Gender)
XY(Years, Salary, form="hexbin", facet=Gender)

# suppress the shared count legend of the faceted hexbin
XY(Years, Salary, form="hexbin", facet=Gender, hexbin_legend=FALSE)
}


#--------------------------------------------------------------
# facet with a vector of x (or y) variables: the multi-series
#   overlay repeated across the panels of the facet variable
#--------------------------------------------------------------

\donttest{
# the Pre and Post overlay against Salary, one panel per Gender level
XY(c(Pre, Post), Salary, facet=Gender)

# the overlay on the y-axis instead: shared Years on the x-axis
XY(Years, c(Pre, Post), facet=Gender, fit="lm")
}



# time charts
#------------
# run chart, with default fill area
XY(.Index, Salary, ts_area_fill="on")

# two run charts in same panel
# or could do a multivariate time series
XY(.Index, c(Pre, Post))

# Trellis graphics run chart with custom line width, no points
XY(.Index, Salary, facet=Gender, line_width=3, pt_size=0)

# daily time series plot
# create the daily time series from R built-in data set airquality
#oz.ts <- ts(airquality$Ozone, start=c(1973, 121), frequency=365)
#XY(oz.ts, data=NULL)

# multiple time series plotted from dates and stacked
# black background with translucent areas, then reset theme to default
style(sub_theme="black", color="steelblue2", transparency=.55,
  window_fill="gray10", grid_color="gray25")
date <- seq(as.Date("2013/1/1"), as.Date("2016/1/1"), by="quarter")
x1 <- rnorm(13, 100, 15)
x2 <- rnorm(13, 100, 15)
x3 <- rnorm(13, 100, 15)
df <- data.frame(date, x1, x2, x3)
rm(date); rm(x1); rm(x2); rm(x3)
XY(date, x1:x3, data=df)
style()

# aggregate monthly data to plot by quarter
n.q <- 42
month <- seq(as.Date("2013/1/1"), length=n.q, by="months")
x <- rnorm(n.q, 100, 15)
XY(month, x, ts_unit="quarters", data=NULL)


# trigger a time series with a Date variable specified first
# stock prices for three companies by month:  Apple, IBM, Intel
d <- rd("StockPrice")
# only plot Apple
XY(Month, Price, filter=(Company=="Apple"))
# Trellis plots, one for each company
XY(Month, Price, facet=Company, n_col=1)
# all three plots on the same panel, three shades of blue
XY(Month, Price, by=Company, color="blues")
# exponential smoothing forecast for next 12 months, 
#   aggregate monthly data by mean over quarters
XY(Month, Price, ts_ahead=12, ts_unit="quarters")

\donttest{


#------------
# annotations
#------------

d <- Read("Employee")

# add text at the one location specified by x1 and x2
XY(Years, Salary, add="Hi There", x1=12, y1=80000)
# add text at three different specified locations
XY(Years, Salary, add="Hi", x1=c(12, 16, 18), y1=c(80000, 100000, 60000))

# add three different text blocks at three different specified locations
XY(Years, Salary, add=c("Hi", "Bye", "Wow"), x1=c(12, 16, 18),
  y1=c(80000, 100000, 60000))

# add an 0.95 data ellipse and horizontal and vertical lines through the
#  respective means
XY(Years, Salary, ellipse=0.95, add=c("v_line", "h_line"),
  x1="mean_x", y1="mean_y")
# can be done also with the following short-hand
XY(Years, Salary, ellipse=0.95, add="means")

# a rectangle requires two points, four coordinates, <x1,y1> and <x2,y2>
style(add_trans=.8, add_fill="gold", add_color="gold4", add_lwd=0.5)
XY(Years, Salary, add="rect", x1=12, y1=80000, x2=16, y2=115000)

# the first object, a rectangle, requires all four coordinates
# the vertical line at x=2 requires only an x1 coordinate, listed 2nd
XY(Years, Salary, add=c("rect", "v_line"), x1=c(10, 2),
  y1=80000, x2=12, y2=115000)

# two different rectangles with different locations, fill colors and translucence
style(add_fill=c("gold3", "green"), add_trans=c(.8,.4))
XY(Years, Salary, add=c("rect", "rect"),
  x1=c(10, 2), y1=c(60000, 45000), x2=c(12, 75000), y2=c(80000, 55000))
}

\donttest{



#---------------
# function curve
#---------------

x <- seq(10,50,by=2)
y1 <- sqrt(x)
y2 <- x**.33
# x is sorted with equal intervals so run chart by default
XY(x, y1, data=NULL)

# multiple plots from variable vectors need to have the variables
#  in a data frame
d <- data.frame(x, y1, y2)
# if variables are in the user workspace and in a data frame
#   with the same names, the user workspace versions are used,
#   which do not work with vectors of variables, so remove
rm(x); rm(y1); rm(y2)
XY(x, c(y1, y2))
}
}


% Add one or more standard keywords, see file 'KEYWORDS' in the
% R documentation directory.
\keyword{ plot }
\keyword{ color }
\keyword{ grouping variable }

