From 4b9c9df79620404476ae13061ebc0249db01f9b2 Mon Sep 17 00:00:00 2001 From: Kohei Watanabe Date: Tue, 17 Jun 2025 17:29:55 +0900 Subject: [PATCH 1/2] Add stat_ksmooth() --- DESCRIPTION | 1 + NAMESPACE | 2 + R/stat-ksmooth.R | 32 ++++++++++++ man/Stat.Rd | 7 +-- man/stat_ksmooth.Rd | 119 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 158 insertions(+), 3 deletions(-) create mode 100644 R/stat-ksmooth.R create mode 100644 man/stat_ksmooth.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 1deed8f79e..147b477911 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -263,6 +263,7 @@ Collate: 'stat-ellipse.R' 'stat-function.R' 'stat-identity.R' + 'stat-ksmooth.R' 'stat-manual.R' 'stat-qq-line.R' 'stat-qq.R' diff --git a/NAMESPACE b/NAMESPACE index 5893c8bb5a..b19478129f 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -254,6 +254,7 @@ export(StatEcdf) export(StatEllipse) export(StatFunction) export(StatIdentity) +export(StatKsmooth) export(StatManual) export(StatQq) export(StatQqLine) @@ -701,6 +702,7 @@ export(stat_ecdf) export(stat_ellipse) export(stat_function) export(stat_identity) +export(stat_ksmooth) export(stat_manual) export(stat_qq) export(stat_qq_line) diff --git a/R/stat-ksmooth.R b/R/stat-ksmooth.R new file mode 100644 index 0000000000..1d0c9bdb22 --- /dev/null +++ b/R/stat-ksmooth.R @@ -0,0 +1,32 @@ +#' @rdname Stat +#' @format NULL +#' @usage NULL +#' @export +StatKsmooth <- ggproto("StatKsmooth", Stat, + required_aes = c("x", "y"), + compute_group = function(data, scales, kernel = "box", bandwidth = 0.5) { + as.data.frame(ksmooth(x = data$x, y = data$y, kernel = kernel, bandwidth = bandwidth)) + } +) + +#' Apply kernel regression smoother +#' +#' @export +#' @inheritParams layer +#' @inheritParams geom_point +#' @inheritParams stats::ksmooth +#' @examples +#' ggplot(economics, aes(date, psavert)) + +#' geom_point(alpha = 0.25) + +#' stat_ksmooth(bandwidth = 180, kernel = "normal") +#' +stat_ksmooth <- function(mapping = NULL, data = NULL, geom = "line", + position = "identity", na.rm = FALSE, show.legend = NA, + inherit.aes = TRUE, kernel = "box", bandwidth = 0.5, + ...) { + layer( + stat = StatKsmooth, data = data, mapping = mapping, geom = geom, + position = position, show.legend = show.legend, inherit.aes = inherit.aes, + params = list(kernel = kernel, bandwidth = bandwidth, ...) + ) +} diff --git a/man/Stat.Rd b/man/Stat.Rd index 5291b47d13..3850f8371f 100644 --- a/man/Stat.Rd +++ b/man/Stat.Rd @@ -3,9 +3,9 @@ % R/stat-summary-2d.R, R/stat-bin2d.R, R/stat-bindot.R, R/stat-binhex.R, % R/stat-boxplot.R, R/stat-connect.R, R/stat-contour.R, R/stat-count.R, % R/stat-density-2d.R, R/stat-density.R, R/stat-ecdf.R, R/stat-ellipse.R, -% R/stat-function.R, R/stat-identity.R, R/stat-manual.R, R/stat-qq-line.R, -% R/stat-qq.R, R/stat-quantilemethods.R, R/stat-smooth.R, R/stat-sum.R, -% R/stat-summary-bin.R, R/stat-summary-hex.R, R/stat-summary.R, +% R/stat-function.R, R/stat-identity.R, R/stat-ksmooth.R, R/stat-manual.R, +% R/stat-qq-line.R, R/stat-qq.R, R/stat-quantilemethods.R, R/stat-smooth.R, +% R/stat-sum.R, R/stat-summary-bin.R, R/stat-summary-hex.R, R/stat-summary.R, % R/stat-unique.R, R/stat-ydensity.R \docType{data} \name{Stat} @@ -28,6 +28,7 @@ \alias{StatEllipse} \alias{StatFunction} \alias{StatIdentity} +\alias{StatKsmooth} \alias{StatManual} \alias{StatQqLine} \alias{StatQq} diff --git a/man/stat_ksmooth.Rd b/man/stat_ksmooth.Rd new file mode 100644 index 0000000000..e43f9c9561 --- /dev/null +++ b/man/stat_ksmooth.Rd @@ -0,0 +1,119 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/stat-ksmooth.R +\name{stat_ksmooth} +\alias{stat_ksmooth} +\title{Apply kernel regression smoother} +\usage{ +stat_ksmooth( + mapping = NULL, + data = NULL, + geom = "line", + position = "identity", + na.rm = FALSE, + show.legend = NA, + inherit.aes = TRUE, + kernel = "box", + bandwidth = 0.5, + ... +) +} +\arguments{ +\item{mapping}{Set of aesthetic mappings created by \code{\link[=aes]{aes()}}. If specified and +\code{inherit.aes = TRUE} (the default), it is combined with the default mapping +at the top level of the plot. You must supply \code{mapping} if there is no plot +mapping.} + +\item{data}{The data to be displayed in this layer. There are three +options: + +If \code{NULL}, the default, the data is inherited from the plot +data as specified in the call to \code{\link[=ggplot]{ggplot()}}. + +A \code{data.frame}, or other object, will override the plot +data. All objects will be fortified to produce a data frame. See +\code{\link[=fortify]{fortify()}} for which variables will be created. + +A \code{function} will be called with a single argument, +the plot data. The return value must be a \code{data.frame}, and +will be used as the layer data. A \code{function} can be created +from a \code{formula} (e.g. \code{~ head(.x, 10)}).} + +\item{geom}{The geometric object to use to display the data for this layer. +When using a \verb{stat_*()} function to construct a layer, the \code{geom} argument +can be used to override the default coupling between stats and geoms. The +\code{geom} argument accepts the following: +\itemize{ +\item A \code{Geom} ggproto subclass, for example \code{GeomPoint}. +\item A string naming the geom. To give the geom as a string, strip the +function name of the \code{geom_} prefix. For example, to use \code{geom_point()}, +give the geom as \code{"point"}. +\item For more information and other ways to specify the geom, see the +\link[=layer_geoms]{layer geom} documentation. +}} + +\item{position}{A position adjustment to use on the data for this layer. This +can be used in various ways, including to prevent overplotting and +improving the display. The \code{position} argument accepts the following: +\itemize{ +\item The result of calling a position function, such as \code{position_jitter()}. +This method allows for passing extra arguments to the position. +\item A string naming the position adjustment. To give the position as a +string, strip the function name of the \code{position_} prefix. For example, +to use \code{position_jitter()}, give the position as \code{"jitter"}. +\item For more information and other ways to specify the position, see the +\link[=layer_positions]{layer position} documentation. +}} + +\item{na.rm}{If \code{FALSE}, the default, missing values are removed with +a warning. If \code{TRUE}, missing values are silently removed.} + +\item{show.legend}{logical. Should this layer be included in the legends? +\code{NA}, the default, includes if any aesthetics are mapped. +\code{FALSE} never includes, and \code{TRUE} always includes. +It can also be a named logical vector to finely select the aesthetics to +display. To include legend keys for all levels, even +when no data exists, use \code{TRUE}. If \code{NA}, all levels are shown in legend, +but unobserved levels are omitted.} + +\item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, +rather than combining with them. This is most useful for helper functions +that define both data and aesthetics and shouldn't inherit behaviour from +the default plot specification, e.g. \code{\link[=annotation_borders]{annotation_borders()}}.} + +\item{kernel}{the kernel to be used. Can be abbreviated.} + +\item{bandwidth}{the bandwidth. The kernels are scaled so that their + quartiles (viewed as probability densities) are at + \eqn{\pm}{+/-} \code{0.25*bandwidth}.} + +\item{...}{Other arguments passed on to \code{\link[=layer]{layer()}}'s \code{params} argument. These +arguments broadly fall into one of 4 categories below. Notably, further +arguments to the \code{position} argument, or aesthetics that are required +can \emph{not} be passed through \code{...}. Unknown arguments that are not part +of the 4 categories below are ignored. +\itemize{ +\item Static aesthetics that are not mapped to a scale, but are at a fixed +value and apply to the layer as a whole. For example, \code{colour = "red"} +or \code{linewidth = 3}. The geom's documentation has an \strong{Aesthetics} +section that lists the available options. The 'required' aesthetics +cannot be passed on to the \code{params}. Please note that while passing +unmapped aesthetics as vectors is technically possible, the order and +required length is not guaranteed to be parallel to the input data. +\item When constructing a layer using +a \verb{stat_*()} function, the \code{...} argument can be used to pass on +parameters to the \code{geom} part of the layer. An example of this is +\code{stat_density(geom = "area", outline.type = "both")}. The geom's +documentation lists which parameters it can accept. +\item Inversely, when constructing a layer using a +\verb{geom_*()} function, the \code{...} argument can be used to pass on parameters +to the \code{stat} part of the layer. An example of this is +\code{geom_area(stat = "density", adjust = 0.5)}. The stat's documentation +lists which parameters it can accept. +\item The \code{key_glyph} argument of \code{\link[=layer]{layer()}} may also be passed on through +\code{...}. This can be one of the functions described as +\link[=draw_key]{key glyphs}, to change the display of the layer in the legend. +}} +} +\description{ +Apply kernel regression smoother +} From 26c3a764a1933bc921dffed4e49c58d8f953b562 Mon Sep 17 00:00:00 2001 From: Kohei Watanabe Date: Tue, 17 Jun 2025 17:39:19 +0900 Subject: [PATCH 2/2] Fix pkgdown --- _pkgdown.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/_pkgdown.yml b/_pkgdown.yml index 701eba5a8d..040697d064 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -78,6 +78,7 @@ reference: - stat_ellipse - stat_function - stat_identity + - stat_ksmooth - stat_summary_2d - stat_summary_bin - stat_unique