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] (0000000279616646) 
Maintainer:  Pepijn de Vries <[email protected]> 
License:  GPL (>= 3) 
Version:  0.0.6.0003 
Built:  20241026 04:57:25 UTC 
Source:  https://github.com/pepijndevries/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 xycoordinates 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 lonlat, 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 xycoordinates 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 lonlat, 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.
geometryx
: 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("ggplot2specs", "ggplot2")
colour
: See vignette("ggplot2specs", "ggplot2")
linetype
: See vignette("ggplot2specs", "ggplot2")
linewidth
: See vignette("ggplot2specs", "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(1e08, 1)) scale_radius_binned(..., range = c(1e08, 1)) scale_radius_discrete(..., range = c(1e08, 1))
scale_radius_continuous(..., range = c(1e08, 1)) scale_radius_binned(..., range = c(1e08, 1)) scale_radius_discrete(..., range = c(1e08, 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 (20161014). doi:10.48670/moi00016
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()