grattan / grattan/grattantheme
Add in geoms for labelled first and final points
Open
@ashleighchangg is already working on this.
Since Dec 11, 2025.
- Dominant language
- R
- Stars
- 24
- Forks
- 6
- Avg merge
- 30m
- Merged PRs (30d)
- 1
Description
These are adaptations of geom_finallabel used by Liz in previous reports.
Initial version:
### geom_firstlabel()
#' Line with a dot on the first observation
#' @description geom_firstlabel() draws a ggplot2::geom_text()
#' at the observation with the maximum x value for each group.
#' @inheritParams ggplot2::geom_text
#' @param nudge_x_perc Amount to nudge label along the x-axis, expressed as a
#' percentage of the data range along the x-axis. The default is 1.5, which
#' will nudge the text 1.5% of the data range from the first point. This is applied
#' in addition to nudge_x, which nudges the text a specific number of data units.
#' @section Aesthetics:
#' \code{geom_text()} understands the following aesthetics (required aesthetics are in bold):
#' \itemize{
#' \item \strong{\code{x}}
#' \item \strong{\code{y}}
#' \item \strong{\code{label}}
#' \item \code{alpha}
#' \item \code{angle}
#' \item \code{colour}
#' \item \code{family}
#' \item \code{fontface}
#' \item \code{group}
#' \item \code{hjust}
#' \item \code{lineheight}
#' \item \code{size}
#' \item \code{vjust}
#' }
#'
#' Learn more about setting these aesthetics in \code{vignette("ggplot2-specs")}.
#' @seealso ggplot2::geom_text
#' @export
#' @rdname geom_firstlabel
#' @examples
#' library(ggplot2)
#'
#'ggplot(ggplot2::economics_long, aes(x = date, y = value)) +
#' geom_linepoint(aes(col = variable)) +
#' geom_firstlabel(aes(label = value)) +
#' facet_wrap(~variable)
geom_firstlabel <-
function(mapping = NULL,
data = NULL,
stat = "identity",
position = "identity",
nudge_x = 0,
nudge_y = 0,
nudge_x_perc = 1.5,
na.rm = FALSE,
show.legend = FALSE,
inherit.aes = TRUE,
...) {
if (!missing(nudge_x) || !missing(nudge_y)) {
if (!missing(position)) {
stop("You must specify either position or nudge_x/nudge_y.")
}
position <- position_nudge(nudge_x, nudge_y)
}
ggplot2::layer(
data = data,
mapping = mapping,
stat = stat,
geom = GeomfirstLabel,
position = position,
show.legend = show.legend,
inherit.aes = inherit.aes,
params = list(
na.rm = na.rm,
nudge_x_perc = nudge_x_perc,
...
)
)
}
#' @export
#' @rdname geom_firstlabel
GeomfirstLabel <- ggplot2::ggproto(
"GeomfirstLabel",
ggplot2::Geom,
extra_params = c("na.rm", "nudge_x_perc"),
setup_data = function(data, params) {
ggplot2::GeomText$setup_data(data, params)
},
draw_group = function(data,
panel_params,
coord,
nudge_x_perc,
flipped_aes = FALSE) {
x_range <- range(data$x)
x_min <- x_range[1]
x_max <- x_range[2]
data <- data[data$x == x_min, ]
data$x <- data$x - ((x_max - x_min) * (nudge_x_perc / 100))
ggplot2::GeomText$draw_panel(
data,
panel_params,
coord
)
},
draw_key = ggplot2::draw_key_text,
required_aes = c("x", "y", "label"),
default_aes = ggplot2::aes(
colour = ggplot2::GeomText$default_aes$colour,
size = ggplot2::GeomText$default_aes$size,
angle = ggplot2::GeomText$default_aes$angle,
hjust = 1,
vjust = ggplot2::GeomText$default_aes$vjust,
alpha = ggplot2::GeomText$default_aes$alpha,
family = ggplot2::GeomText$default_aes$family,
fontface = ggplot2::GeomText$default_aes$fontface,
lineheight = 0.9
)
)
#' Line with a dot on the final observation
#' @description geom_linepoint() draws a ggplot2::geom_line() and adds a
#' ggplot2::geom_point() at the observation with the maximum x value for each
#' group.
#' @inheritParams ggplot2::geom_line
#' @section Aesthetics:
#' \code{geom_linepoint()} understands the following aesthetics (required aesthetics are in bold):
#' \itemize{
#' \item \strong{\code{x}}
#' \item \strong{\code{y}}
#' \item \code{alpha}
#' \item \code{colour}
#' \item \code{group}
#' \item \code{linetype}
#' \item \code{pointfill}
#' \item \code{pointshape}
#' \item \code{pointsize}
#' \item \code{pointstroke}
#' \item \code{pointshape}
#' \item \code{linewidth}
#' \item \code{weight}
#' }
#' The aesthetics that begin with 'point' (eg. pointfill) are passed to
#' geom_point() - for example pointfill is passed to the fill aesthetic
#' of geom_point().
#'
#' The x, y, alpha, colour, and group aesthetics are passed to both
#' geom_line() and geom_point().
#'
#' The linetype, linewidth, and weight aesthetics are passed to geom_line().
#'
#' Learn more about setting these aesthetics in \code{vignette("ggplot2-specs")}.
#' @seealso ggplot2::geom_line, ggplot2::geom_point
#' @rdname geom_linepoint
#' @export
#' @examples
#' library(ggplot2)
#'
#'ggplot(ggplot2::economics_long, aes(x = date, y = value)) +
#' geom_linepoint(aes(col = variable)) +
#' facet_wrap(~variable)
geom_linepoint <-
function(mapping = NULL,
data = NULL,
stat = "identity",
position = "identity",
na.rm = FALSE,
show.legend = NA,
inherit.aes = TRUE,
...) {
ggplot2::layer(
data = data,
mapping = mapping,
stat = stat,
geom = GeomLinePoint,
position = position,
show.legend = show.legend,
inherit.aes = inherit.aes,
params = list(
na.rm = na.rm,
...
)
)
}
#' @rdname geom_linepoint
#' @export
GeomLinePoint <- ggplot2::ggproto(
"GeomLinePoint",
ggplot2::Geom,
extra_params = c("na.rm"),
setup_data = function(data, params) {
ggplot2::GeomLine$setup_data(data, params)
},
draw_group = function(data,
panel_params,
coord,
lineend = "butt",
linejoin = "round",
linemitre = 10,
size = 5,
flipped_aes = FALSE) {
point <- data
point <- point[point$x == point$x[length(point$x)], ]
point$size <- point$pointsize
point$fill <- point$pointfill
point$shape <- point$pointshape
point$stroke <- point$pointstroke
point$shape <- point$pointshape
if (utils::packageVersion("ggplot2") < "3.4.0") {
names(data)[names(data) == "linewidth"] <- "size"
}
path <- transform(data, alpha = NA)
grid::gList(
ggplot2::GeomLine$draw_panel(
path,
panel_params,
coord,
lineend = lineend,
linejoin = linejoin,
linemitre = linemitre
),
ggplot2::GeomPoint$draw_panel(point, panel_params, coord)
)
},
draw_key = ggplot2::draw_key_smooth,
required_aes = c("x", "y"),
non_missing_aes = c(
"linewidth", "shape", "colour", "pointsize",
"pointstroke", "pointfill", "pointshape"
),
default_aes = ggplot2::aes(
pointsize = 2.5,
pointfill = "white",
pointshape = 21,
shape = 19,
colour = "black",
linewidth = 1,
alpha = 1,
pointstroke = 1.5,
linetype = 1,
weight = 1
)
)
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.