Skip to content

Commit

Permalink
Add geom_points_range(); rearrange some vignette stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
willgearty committed Jan 11, 2024
1 parent 948e1a5 commit 1a629dc
Show file tree
Hide file tree
Showing 18 changed files with 1,581 additions and 27 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ Imports:
lifecycle
Suggests:
dplyr,
magrittr,
divDyn,
gsloid,
ape,
palaeoverse,
paleotree,
dispRity,
ggtree (>= 3.6.1),
Expand Down
8 changes: 8 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export(coord_trans_flip)
export(coord_trans_xy)
export(disparity_through_time)
export(geom_phylomorpho)
export(geom_points_range)
export(getScaleData)
export(get_scale_data)
export(ggarrange2)
Expand All @@ -26,6 +27,7 @@ export(scale_color_geo)
export(scale_colour_geo)
export(scale_discrete_geo)
export(scale_fill_geo)
export(stat_points_range)
import(scales)
importFrom(cli,cli_abort)
importFrom(curl,nslookup)
Expand All @@ -36,6 +38,9 @@ importFrom(ggplot2,CoordCartesian)
importFrom(ggplot2,CoordFlip)
importFrom(ggplot2,CoordPolar)
importFrom(ggplot2,CoordTrans)
importFrom(ggplot2,Geom)
importFrom(ggplot2,GeomLinerange)
importFrom(ggplot2,GeomPoint)
importFrom(ggplot2,Stat)
importFrom(ggplot2,aes)
importFrom(ggplot2,annotate)
Expand All @@ -45,6 +50,7 @@ importFrom(ggplot2,coord_flip)
importFrom(ggplot2,coord_polar)
importFrom(ggplot2,coord_trans)
importFrom(ggplot2,discrete_scale)
importFrom(ggplot2,draw_key_pointrange)
importFrom(ggplot2,expansion)
importFrom(ggplot2,geom_rect)
importFrom(ggplot2,geom_segment)
Expand All @@ -55,13 +61,15 @@ importFrom(ggplot2,ggplotGrob)
importFrom(ggplot2,ggplot_build)
importFrom(ggplot2,ggproto)
importFrom(ggplot2,ggproto_parent)
importFrom(ggplot2,has_flipped_aes)
importFrom(ggplot2,last_plot)
importFrom(ggplot2,layer)
importFrom(ggplot2,scale_color_manual)
importFrom(ggplot2,scale_fill_manual)
importFrom(ggplot2,scale_x_continuous)
importFrom(ggplot2,scale_x_reverse)
importFrom(ggplot2,set_last_plot)
importFrom(ggplot2,standardise_aes_names)
importFrom(ggplot2,theme_void)
importFrom(grDevices,dev.interactive)
importFrom(grDevices,dev.new)
Expand Down
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# deeptime (development version)

* Fixed the interaction between coord_geo() and ggsave() (#49)
* Added geom_points_range(), a function designed for visualizing temporal occurrence data

# deeptime 1.0.1

Expand Down
194 changes: 194 additions & 0 deletions R/points_range.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
#' Display points and their range
#'
#' This geom is like [ggplot2::geom_pointrange()] in that it draws points and
#' lines. However, unlike [ggplot2::geom_pointrange()], this geom takes in sets
#' of x-y points and calculates the ranges/intervals based on those. It then
#' plots both the original points and the ranges using
#' [ggplot2::geom_linerange()]. In cases where not all points are connected
#' (because of grouping due to aesthetics), the `background_line` argument can
#' be used to add lines that span the entire point range for each `x` or `y`
#' category.
#'
#' @section Aesthetics: \code{geom_points_range()} understands the following
#' aesthetics (required aesthetics are in bold):
#'
#' - **x**
#' - **y**
#' - size
#' - color/colour
#' - fill
#' - shape
#' - alpha
#' - group
#' - linetype
#' - linewidth
#'
#' @param background_line A named list of aesthetic values to use for plotted
#' line segments that span the entire `y` or `x` range for each `x` or `y`
#' category. The default aesthetics will be used for any aesthetics that are
#' not specified in the list. If NULL (the default), no line segments will be
#' plotted.
#' @param ... Arguments passed on to both [ggplot2::geom_linerange()] and
#' [ggplot2::geom_point()].
#' @importFrom ggplot2 layer
#' @inheritParams ggplot2::geom_pointrange
#' @inheritSection ggplot2::geom_pointrange Orientation
#' @export
#' @examples
#' library(ggplot2)
#' @examplesIf require(palaeoverse)
#' library(palaeoverse)
#' data(tetrapods)
#' tetrapod_names <- tetrapods$accepted_name[1:50]
#' beds_sampled <- sample.int(n = 10, size = 50, replace = TRUE)
#' occdf <- data.frame(taxon = tetrapod_names, bed = beds_sampled)
#' ggplot(occdf, aes(y = reorder(taxon, bed, min), x = bed)) +
#' geom_points_range()
geom_points_range <- function(mapping = NULL, data = NULL,
stat = "points_range", position = "identity",
...,
na.rm = FALSE, orientation = NA,
background_line = NULL,
show.legend = NA, inherit.aes = TRUE) {
layer(
data = data,
mapping = mapping,
stat = stat,
geom = GeomPointsRange,
position = position,
show.legend = show.legend,
inherit.aes = inherit.aes,
params = list(na.rm = na.rm, orientation = orientation,
background_line = background_line, ...)
)
}

#' @rdname geom_points_range
#' @section Computed variables: These are calculated by the 'stat' part of
#' layers and can be accessed with [delayed evaluation][ggplot2::aes_eval].
#' \code{stat_points_range()} provides the following variables, some of which
#' depend on the orientation:
#' \itemize{
#' \item \code{after_stat(ymin)} \emph{or} \code{after_stat(xmin)}\cr
#' the minimum extent of the point range
#' \item \code{after_stat(ymax)} \emph{or} \code{after_stat(xmax)}\cr
#' the maximum extent of the point range
#' }
#' @importFrom ggplot2 layer
#' @inheritParams ggplot2::stat_identity
#' @export
stat_points_range <- function(mapping = NULL, data = NULL,
geom = "points_range", position = "identity",
...,
na.rm = FALSE, orientation = NA,
show.legend = NA, inherit.aes = TRUE) {
layer(
data = data,
mapping = mapping,
stat = StatPointsRange,
geom = geom,
position = position,
show.legend = show.legend,
inherit.aes = inherit.aes,
params = list(na.rm = na.rm, orientation = orientation, ...)
)
}

#' @importFrom ggplot2 ggproto Stat has_flipped_aes
StatPointsRange <- ggproto("StatPointsRange", Stat,
required_aes = c("x", "y"),
extra_params = c("na.rm", "orientation"),
setup_params = function(self, data, params) {
params$flipped_aes <- has_flipped_aes(data, params,
main_is_orthogonal = TRUE,
group_has_equal = TRUE,
main_is_optional = TRUE)
params
},
setup_data = function(self, data, params) {
data <- flip_data(data, params$flipped_aes)
data <- remove_missing(
data,
na.rm = params$na.rm,
vars = "x",
name = "stat_points_range"
)
flip_data(data, params$flipped_aes)
},
compute_group = function(data, scales, na.rm = FALSE, flipped_aes = FALSE) {
# flip the data if needed
data <- flip_data(data, flipped_aes)
# calculate the y ranges
data <- transform(data,
ymin = min(y, na.rm = na.rm),
ymax = max(y, na.rm = na.rm))
# flip the data back if needed
data <- flip_data(data, flipped_aes)
data
},
)

#' @importFrom ggplot2 ggproto Geom GeomPoint GeomLinerange draw_key_pointrange
#' @importFrom ggplot2 standardise_aes_names
#' @importFrom grid gList gTree
GeomPointsRange <- ggproto("GeomPointsRange", Geom,
required_aes = c("x", "y", "ymin|xmin", "ymax|xmax"),
extra_params = c("na.rm", "orientation"),
default_aes = aes(shape = 19, colour = "black", size = 0.5, fill = NA,
alpha = NA, stroke = 0.5,
linewidth = 0.5, linetype = 1),
draw_key = draw_key_pointrange,
setup_params = function(self, data, params) {
params$flipped_aes <- has_flipped_aes(data, params)
params
},
setup_data = function(data, params) {
data
},
draw_panel = function(self, data, panel_params, coord, fatten = 4,
flipped_aes = FALSE, background_line = NULL,
na.rm = FALSE) {
grob_list <- gList()
if (!is.null(background_line)) {
# flip the data if needed
data <- flip_data(data, flipped_aes)
# split the data and calculate a full y range for each x category
lst <- split(data, data$x)
lst <- lapply(lst, function(df) {
data.frame(x = unique(df$x), PANEL = unique(data$PANEL),
ymin = min(df$y), ymax = max(df$y))
})
# put it all together and
df <- do.call(rbind, lst)
for (name in names(background_line)) {
df[[name]] <- background_line[[name]]
}
df <- flip_data(df, flipped_aes)
names(df) <- standardise_aes_names(names(df))
df <- self$use_defaults(df)
# add background lines as a grob
grob_list <- gList(grob_list,
GeomLinerange$draw_panel(df, panel_params, coord,
flipped_aes = flipped_aes,
na.rm = na.rm))
# flip the data back if needed
data <- flip_data(data, flipped_aes)
}
# add the normal grobs
grob_list <- gList(
grob_list,
GeomLinerange$draw_panel(unique(data), panel_params, coord,
flipped_aes = flipped_aes, na.rm = na.rm),
GeomPoint$draw_panel(transform(data, size = size * fatten),
panel_params, coord, na.rm = na.rm)
)
gTree(name = "geom_points_range", children = grob_list)
},
)

#' @importFrom grid grobName
ggname <- function(prefix, grob) {
# copied from ggplot2
grob$name <- grobName(grob, prefix)
grob
}
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ devtools::install_github("willgearty/deeptime")
```r
library(deeptime)
library(dplyr)
library(magrittr)
```

### Add timescales to plots
Expand Down
27 changes: 17 additions & 10 deletions _pkgdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ articles:
contents:
- coord_geo
- phylogenies
- coord
- traits
- time
- ggarrange2
- coord

reference:
- title: Adding geological timescales to plots
Expand Down Expand Up @@ -80,6 +81,14 @@ reference:
- scale_color_geo
- get_scale_data

- title: Transforming coordinate systems
desc: >
These functions can be used to modify the way that your data is plotted
by `{ggplot2}`.
contents:
- coord_trans_flip
- coord_trans_xy

- title: Plotting trait data
desc: >
These functions can be used for visualizing species trait data.
Expand All @@ -89,19 +98,17 @@ reference:
- panel.disparity
- coord_trans_xy

- title: Plotting temporal data
desc: >
These functions can be used for visualizing temporal data.
contents:
- geom_points_range
- stat_points_range

- title: Combining and arranging plots
desc: >
These functions can be used to combine and arrange plots into
publishable-quality figures.
contents:
- ggarrange2
- gtable_frame2

- title: Transforming coordinate systems
desc: >
These functions can be used to modify the way that your data is plotted
by `{ggplot2}`.
contents:
- coord_trans_flip
- coord_trans_xy

Loading

0 comments on commit 1a629dc

Please sign in to comment.