Title: | Add Vector Field Layers to Ggplots |
---|---|
Description: | Add vector field layers to ggplots. Ideal for visualising wind speeds, water currents, electric/magnetic fields, etc. Accepts data.frames, simple features (sf), and spatiotemporal arrays (stars) objects as input. Vector fields are depicted as arrows starting at specified locations, and with specified angles and radii. |
Authors: | Pepijn de Vries [aut, cre] (0000-0002-7961-6646) |
Maintainer: | Pepijn de Vries <[email protected]> |
License: | GPL (>= 3) |
Version: | 0.0.6.0003 |
Built: | 2024-10-26 04:57:25 UTC |
Source: | https://github.com/pepijn-devries/ggfields |
The angle of a vector may be distorted when your plot uses a different
coordinate system than the one for which the angle is specified. If data
is a simple feature object (sf), the angle will be corrected
for the displayed coordinate reference system (crs). When
the crs is missing, an aspect ratio of 1 is assumed. For any other data,
the angle is corrected for the aspect ratio in the plot.
angle_correction(data, panel_params, coord)
angle_correction(data, panel_params, coord)
data |
fortified data used in a |
panel_params |
panel parameters as returned by GeomFields$setup_params() |
coord |
A coord object. |
This function is used by default by geom_fields()
. For more details on
why this correction is required and how to customize corrections please see
vignette("angle_correction")
.
A data.frame
with an additional angle_correction
column. The corrected angle is given
by angle_correction + angle
.
Pepijn de Vries
## Create a data.frame with some xy-coordinates and all angles pointing North (0 degrees) d <- data.frame( x = seq(1, 2, 0.1), y = seq(50, 51, 0.1), angle = 0 ) |> sf::st_as_sf(coords = c("x", "y"), crs = 4326, remove = FALSE) ## Create a mockup of ggplot params. Normally this is handled automatically by ggplot2 params_mockup <- c( ggplot2::ggplot() + geom_fields(), list( x_range = range(d$x), y_range = range(d$y), crs = sf::st_crs(4326), default_crs = 4326 ) ) ## When plotting as lon-lat, the angle correction will be zero angle_correction(d, params_mockup, ggplot2::coord_sf(default_crs = 4326)) ## Transform to UTM zone 31N in meters d2 <- d |> sf::st_transform(32631) ## Again get parameter mockup values params_mockup2 <- c( ggplot2::ggplot() + geom_fields(), list( x_range = range(sf::st_coordinates(d2)[,1]), y_range = range(sf::st_coordinates(d2)[,1]), crs = sf::st_crs(32631), default_crs = 4326 ) ) ## in UTM projection in this area (which is slightly tilted) the correction is ## larger than zero angle_correction(d2, params_mockup2, ggplot2::coord_sf(crs = 32631, default_crs = 4326))
## Create a data.frame with some xy-coordinates and all angles pointing North (0 degrees) d <- data.frame( x = seq(1, 2, 0.1), y = seq(50, 51, 0.1), angle = 0 ) |> sf::st_as_sf(coords = c("x", "y"), crs = 4326, remove = FALSE) ## Create a mockup of ggplot params. Normally this is handled automatically by ggplot2 params_mockup <- c( ggplot2::ggplot() + geom_fields(), list( x_range = range(d$x), y_range = range(d$y), crs = sf::st_crs(4326), default_crs = 4326 ) ) ## When plotting as lon-lat, the angle correction will be zero angle_correction(d, params_mockup, ggplot2::coord_sf(default_crs = 4326)) ## Transform to UTM zone 31N in meters d2 <- d |> sf::st_transform(32631) ## Again get parameter mockup values params_mockup2 <- c( ggplot2::ggplot() + geom_fields(), list( x_range = range(sf::st_coordinates(d2)[,1]), y_range = range(sf::st_coordinates(d2)[,1]), crs = sf::st_crs(32631), default_crs = 4326 ) ) ## in UTM projection in this area (which is slightly tilted) the correction is ## larger than zero angle_correction(d2, params_mockup2, ggplot2::coord_sf(crs = 32631, default_crs = 4326))
Functions exactly the same as geom_fields()
, with that difference
that this function does not train the x
and y
scales. This
makes the data central, and uses this layer to support it. Consequently,
annotation_fields()
does not accept a stat
argument.
annotation_fields( mapping = NULL, data = NULL, position = "identity", na.rm = FALSE, show.legend = NA, max_radius = ggplot2::unit(0.5, "cm"), .angle_correction = angle_correction, arrow = grid::arrow(length = ggplot2::unit(0.2, "cm")), inherit.aes = TRUE, ... )
annotation_fields( mapping = NULL, data = NULL, position = "identity", na.rm = FALSE, show.legend = NA, max_radius = ggplot2::unit(0.5, "cm"), .angle_correction = angle_correction, arrow = grid::arrow(length = ggplot2::unit(0.2, "cm")), inherit.aes = TRUE, ... )
mapping |
Set of aesthetic mappings created by |
data |
Can be one of four things:
|
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
|
na.rm |
If |
show.legend |
logical. Should this layer be included in the legends?
|
max_radius |
Maximum radius to which the |
.angle_correction |
Function to correct the angle in the aesthetics for the projection and/or
aspect ratio used in the plot. When set to |
arrow |
specification for arrow heads, as created by |
inherit.aes |
If |
... |
Other arguments passed on to
|
Pepijn de Vries
if (requireNamespace("stars") && requireNamespace("ggplot2")) { library(stars) library(ggplot2) data("seawatervelocity") sw_sub <- seawatervelocity[,8:13,1:5] ## Note that the `seawatervelocity` spans a much larger area, ## but the plot only focuses on `sw_sub` ggplot() + geom_stars(data = sw_sub) + annotation_fields(data = seawatervelocity, aes(angle = as.numeric(atan2(vo, uo)), radius = as.numeric(pythagoras(uo, vo)))) + labs(radius = "v [m/s]") }
if (requireNamespace("stars") && requireNamespace("ggplot2")) { library(stars) library(ggplot2) data("seawatervelocity") sw_sub <- seawatervelocity[,8:13,1:5] ## Note that the `seawatervelocity` spans a much larger area, ## but the plot only focuses on `sw_sub` ggplot() + geom_stars(data = sw_sub) + annotation_fields(data = seawatervelocity, aes(angle = as.numeric(atan2(vo, uo)), radius = as.numeric(pythagoras(uo, vo)))) + labs(radius = "v [m/s]") }
Each geom has an associated function that draws the key when the geom needs
to be displayed in a legend. These functions are called draw_key_*()
, where
*
stands for the name of the respective key glyph. The key glyphs can be
customized for individual geoms by providing a geom with the key_glyph
argument (see layer()
or examples below.)
draw_key_fields(data, params, size)
draw_key_fields(data, params, size)
data |
A single row data frame containing the scaled aesthetics to display in this key |
params |
A list of additional parameters supplied to the geom. |
size |
Width and height of key in mm. |
The layer geom_fields()
allows for a special aesthetic radius
. This function
draws a key glyph for this aesthetics, where the radius of the arrow corresponds
with the scalar value listed with this radius. Note that the width of the key glyph
cannot be adjusted by the aesthetic itself. Therefore, if your max_radius
parameter
exceeds the glyph width, you need to change the width of the guides yourself,
see vignette("radius_aes")
for more details.
A grid grob
Pepijn de Vries
if (requireNamespace("ggplot2")) { library(ggplot2) p <- ggplot(economics, aes(date, psavert, color = "savings rate")) p + geom_line(key_glyph = "fields") }
if (requireNamespace("ggplot2")) { library(ggplot2) p <- ggplot(economics, aes(date, psavert, color = "savings rate")) p + geom_line(key_glyph = "fields") }
Visualise vector fields (such as, electric/magnetic fields, wind speed, or water currents) with arrows as a layer in a ggplot.
GeomFields geom_fields( mapping = NULL, data = NULL, stat = "fields", position = "identity", na.rm = FALSE, show.legend = NA, max_radius = ggplot2::unit(0.5, "cm"), .angle_correction = angle_correction, arrow = grid::arrow(length = ggplot2::unit(0.2, "cm")), inherit.aes = TRUE, ... )
GeomFields geom_fields( mapping = NULL, data = NULL, stat = "fields", position = "identity", na.rm = FALSE, show.legend = NA, max_radius = ggplot2::unit(0.5, "cm"), .angle_correction = angle_correction, arrow = grid::arrow(length = ggplot2::unit(0.2, "cm")), inherit.aes = TRUE, ... )
mapping |
Set of aesthetic mappings created by |
data |
Can be one of four things:
|
stat |
The statistical transformation to use on the data for this layer. By default it is
set to |
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
|
na.rm |
If |
show.legend |
logical. Should this layer be included in the legends?
|
max_radius |
Maximum radius to which the |
.angle_correction |
Function to correct the angle in the aesthetics for the projection and/or
aspect ratio used in the plot. When set to |
arrow |
specification for arrow heads, as created by |
inherit.aes |
If |
... |
Other arguments passed on to
|
An object of class GeomFields
(inherits from GeomSegment
, Geom
, ggproto
, gg
) of length 8.
Adds a layer with vector fields to a ggplot. In order to achieve this
two special aesthetic are required: radius
and angle
.
A layer which can be added to a ggplot.
geometry|x
: Either a geometry
column or x
coordinate.
In case of geometry
the column should be of class sf::sfc_POINT.
In case of x
, it should be a numeric
vector
, and the aesthetic
y
needs to be specified as well. It specifies the location of
the origin of each vector.
radius
: This aesthetic will be used to scale the radius of the
vector arrows in the field you wish to display. The maximum radius of the
arrows is given by parameter max_radius
. See vignette("radius_aes")
for
more details.
angle
: This aesthetic represent the angles of the vectors in your
field in radians. Contrary to the mathematical definition, an angle of 0 radians will
point upwards (instead of to the right). This was chosen such because in most geographical
applications an angle of zero degrees points Northwards. Before plotting these angles are
corrected by the function passed to the .angle_correction
argument.
See vignette("angle_corrections)
for more details.
y
: This aesthetic needs to be used in combination with the x
aesthetic.
It needs to be a numeric
vector
.
fill
: See vignette("ggplot2-specs", "ggplot2")
colour
: See vignette("ggplot2-specs", "ggplot2")
linetype
: See vignette("ggplot2-specs", "ggplot2")
linewidth
: See vignette("ggplot2-specs", "ggplot2")
alpha
: A variable to control the opacity of an element.
Pepijn de Vries
data(seawatervelocity) if (requireNamespace("ggplot2") && requireNamespace("stars") && requireNamespace("scales")) { library(ggplot2) library(stars) sw_df <- as.data.frame(seawatervelocity) ggplot(sw_df, aes(x = x, y = y, radius = as.numeric(v), angle = as.numeric(angle))) + geom_fields(max_radius = unit(0.5, "cm"), na.rm = TRUE) ggplot() + geom_fields(data = seawatervelocity, mapping = aes(radius = as.numeric(v), angle = as.numeric(angle), col = as.numeric(v)), max_radius = unit(0.5, "cm")) + scale_colour_viridis_c() }
data(seawatervelocity) if (requireNamespace("ggplot2") && requireNamespace("stars") && requireNamespace("scales")) { library(ggplot2) library(stars) sw_df <- as.data.frame(seawatervelocity) ggplot(sw_df, aes(x = x, y = y, radius = as.numeric(v), angle = as.numeric(angle))) + geom_fields(max_radius = unit(0.5, "cm"), na.rm = TRUE) ggplot() + geom_fields(data = seawatervelocity, mapping = aes(radius = as.numeric(v), angle = as.numeric(angle), col = as.numeric(v)), max_radius = unit(0.5, "cm")) + scale_colour_viridis_c() }
Calculates the length of a vector using the Pythagorean theorem.
pythagoras(x, y)
pythagoras(x, y)
x |
A |
y |
A |
Returns a numeric
vector
with the same length as x
and y
,
reflecting the lengths of the hypotenuse of the right triangles.
Pepijn de Vries
pythagoras(x = c(1, 2), y = c(1, 2))
pythagoras(x = c(1, 2), y = c(1, 2))
Scales to set up the visualisation of the radius
aesthetic. These
scales are also automatically used in plot guides.
Note that scale_radius_identity()
does not exist as it would be impossible to
relate such a scale to the max_radius
parameter. For more details see
vignette("radius_aes")
.
scale_radius_continuous(..., range = c(1e-08, 1)) scale_radius_binned(..., range = c(1e-08, 1)) scale_radius_discrete(..., range = c(1e-08, 1))
scale_radius_continuous(..., range = c(1e-08, 1)) scale_radius_binned(..., range = c(1e-08, 1)) scale_radius_discrete(..., range = c(1e-08, 1))
... |
Arguments passed on to underpinning |
range |
Relative output range of radii. Must lie between 0 and 1. |
An object of class Scale.
Pepijn de Vries
if (requireNamespace("ggplot2")) { library(ggplot2) data(seawatervelocity) g_num <- ggplot() + geom_fields(data = seawatervelocity, aes(radius = as.numeric(v), angle = as.numeric(angle))) g_discr <- ggplot() + geom_fields(data = seawatervelocity, aes(radius = cut(as.numeric(v), 4), angle = as.numeric(angle))) g_num + scale_radius_continuous() g_num + scale_radius_binned() g_discr + scale_radius_discrete() }
if (requireNamespace("ggplot2")) { library(ggplot2) data(seawatervelocity) g_num <- ggplot() + geom_fields(data = seawatervelocity, aes(radius = as.numeric(v), angle = as.numeric(angle))) g_discr <- ggplot() + geom_fields(data = seawatervelocity, aes(radius = cut(as.numeric(v), 4), angle = as.numeric(angle))) g_num + scale_radius_continuous() g_num + scale_radius_binned() g_discr + scale_radius_discrete() }
A small subset of ocean currents data retrieved with CopernicusMarine from the source listed below serving as an example.
A stars object with x
, y
, depth
and time
dimensions. It has the
attributes vo
(northward seawater velocity [m/s]) and uo
(eastward seawater velocity [m/s]).
E.U. Copernicus Marine Service Information; Global Ocean Physics Analysis and Forecast - GLOBAL_ANALYSISFORECAST_PHY_001_024 (2016-10-14). doi:10.48670/moi-00016
data("seawatervelocity")
data("seawatervelocity")
Prepares data before being handled by geom_fields()
StatFields stat_fields( mapping = NULL, data = NULL, geom = "fields", position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, ... )
StatFields stat_fields( mapping = NULL, data = NULL, geom = "fields", position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, ... )
mapping |
Set of aesthetic mappings created by |
data |
Can be one of four things:
|
geom |
The layer type for which the data is prepared. In this case |
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
|
na.rm |
If |
show.legend |
logical. Should this layer be included in the legends?
|
inherit.aes |
If |
... |
Other arguments passed on to
|
An object of class StatFields
(inherits from StatSf
, Stat
, ggproto
, gg
) of length 3.
Returns a layer that can be further modified by geom_fields()
.
Pepijn de Vries
stat_fields()
stat_fields()