| Title: | Plot Records per Time of Day |
|---|---|
| Description: | Splits date and time of day components from continuous 'datetime' objects, then plots them using grammar of graphics ('ggplot2'). Plots can also be decorated with solar cycle information (e.g., sunset, sunrise, etc.). This is useful for visualising data that are associated with the solar cycle. |
| Authors: | Pepijn de Vries [aut, cre] (0000-0002-7961-6646), Sander Lagerveld [dtc] (0000-0003-1291-4021) |
| Maintainer: | Pepijn de Vries <[email protected]> |
| License: | GPL (>= 3) |
| Version: | 0.0.3.0001 |
| Built: | 2026-05-10 08:09:59 UTC |
| Source: | https://github.com/pepijn-devries/gghourglass |
Adds rectangles to a geom_hourglass() plot layer. It can be used to
mark specific periods. The example shows how this annotation can be
used to mark the periods when detector (used for the observations) was active.
Note that this may not work correctly when displaying data that uses
datetime objects with daylight saving time. In those cases you could
split the periods into parts with and without daylight saving. Or convert
your data to a timezone without daylight saving time (e.g. UTC).
annotate_periodstates(mapping, data, hour_center = 0, ...)annotate_periodstates(mapping, data, hour_center = 0, ...)
mapping |
A |
data |
A |
hour_center |
The hour at which the time of day is centred. Default is 0, meaning midnight. -12 centres around noon of the preceding day, +12 centres around noon of the next day. |
... |
Passed to layer parameters. |
Pepijn de Vries
library(ggplot2) library(dplyr) library(lubridate) ## Extract monitoring periods from 'bats' data monitoring_periods <- attr(bats, "monitoring") |> mutate(time_on = as_datetime(time_on), time_off = as_datetime(time_off)) ggplot(bats, aes(x = RECDATETIME, col = SPECDESCSCI)) + ## Set background to transparent red to contrast with ## monitoring periods theme(panel.background = element_rect(fill = "#FF000044")) + ## Annotate periods in which the detector was active with ## white rectangles annotate_periodstates( aes(x = start, xend = end, y = time_on, yend = time_off), monitoring_periods, fill = "white") + ## plot observations geom_hourglass(hour_center = -6)library(ggplot2) library(dplyr) library(lubridate) ## Extract monitoring periods from 'bats' data monitoring_periods <- attr(bats, "monitoring") |> mutate(time_on = as_datetime(time_on), time_off = as_datetime(time_off)) ggplot(bats, aes(x = RECDATETIME, col = SPECDESCSCI)) + ## Set background to transparent red to contrast with ## monitoring periods theme(panel.background = element_rect(fill = "#FF000044")) + ## Annotate periods in which the detector was active with ## white rectangles annotate_periodstates( aes(x = start, xend = end, y = time_on, yend = time_off), monitoring_periods, fill = "white") + ## plot observations geom_hourglass(hour_center = -6)
Annotate a ggplot (currently only plots using coord_hourglass()
is supported) with a coloured band indicating solar events, such
as sunset and sunrise.
AnnotateDaylight annotate_daylight( longitude = 0, latitude = 60, sun_prop = c("sunrise", "sunset"), ... )AnnotateDaylight annotate_daylight( longitude = 0, latitude = 60, sun_prop = c("sunrise", "sunset"), ... )
longitude, latitude
|
Geographical location that will be used to calculate sunlight times. |
sun_prop |
A vector of two solar events that should be
captured by the annotation. It will be shown as a coloured band
between these two events. Default is |
... |
Passed to the list of layer parameters. |
An object of class AnnotateDaylight (inherits from GeomPolygon, Geom, ggproto, gg) of length 6.
Returns a ggplot2::layer() which can be added to a ggplot2::ggplot()
Pepijn de Vries
library(ggplot2) data(bats) monitoring <- attr(bats, "monitoring") ggplot(subset(bats, format(RECDATETIME, "%Y") == "2018"), aes(x = RECDATETIME, col = SPECDESCSCI)) + annotate_daylight(monitoring$longitude[1], monitoring$latitude[1], c("sunset", "sunrise")) + annotate_daylight(monitoring$longitude[1], monitoring$latitude[1], c("dusk", "dawn")) + geom_hourglass()library(ggplot2) data(bats) monitoring <- attr(bats, "monitoring") ggplot(subset(bats, format(RECDATETIME, "%Y") == "2018"), aes(x = RECDATETIME, col = SPECDESCSCI)) + annotate_daylight(monitoring$longitude[1], monitoring$latitude[1], c("sunset", "sunrise")) + annotate_daylight(monitoring$longitude[1], monitoring$latitude[1], c("dusk", "dawn")) + geom_hourglass()
This function uses the suncalc package to calculate the lunar phase
and uses it to annotate your plot. If your plot has an axis with a
continuous datetime scale, lunar phases are plot along this axis.
Otherwise you have to specify the date of the lunar phase.
AnnotateLunarphase annotate_lunarphase( date = NULL, longitude = NULL, latitude = NULL, breaks = ggplot2::waiver(), placement = 0.9, radius = grid::unit(5, "mm"), n = 26, ... )AnnotateLunarphase annotate_lunarphase( date = NULL, longitude = NULL, latitude = NULL, breaks = ggplot2::waiver(), placement = 0.9, radius = grid::unit(5, "mm"), n = 26, ... )
date |
A datetime object used to calculate the illuminated fraction of the moon |
longitude, latitude
|
Used to calculate zenith angle. This will result in a more accurate shape of the moon as observed at the specified location. |
breaks |
One of:
|
placement |
Relative placement of the lunar annotation in the plotting panel. It should be between 0 and 1. Default is 0.9. |
radius |
Size of the lunar pictogram. It is best to use an absolute
unit from the |
n |
Number of coordinates in the returned polygon shape (should be even). |
... |
Passed to the list of layer parameters. |
An object of class AnnotateLunarphase (inherits from GeomPolygon, Geom, ggproto, gg) of length 6.
Returns a ggplot2::layer() which can be added to a ggplot2::ggplot()
Pepijn de Vries
library(ggplot2) library(dplyr) library(lubridate) data(bats) monitoring <- attr(bats, "monitoring") ## A lunar annotation can be added to a geom_hourglass layer ggplot(mutate(bats, YEAR = year(RECDATETIME), MONTH = month(RECDATETIME)) |> filter(YEAR == 2018, MONTH == 5), aes(x = RECDATETIME, col = SPECDESCSCI)) + geom_hourglass() + annotate_lunarphase( longitude = monitoring$longitude[[1]], latitude = monitoring$latitude[[1]], placement = 0.8) + scale_x_datetime(limits = as_datetime(c("2018-04-27", "2018-05-31"))) ## In fact, it can be added to any plot with a continuous datetime scale ggplot(data.frame(stamp = seq(as_datetime("2025-04-01 UTC"), as_datetime("2025-04-30 UTC"), length.out = 20), value = 1:20), aes(x = stamp, y = value)) + geom_point() + annotate_lunarphase() ## Moreover, you can add it to an arbitrary plot without such scales, ## but then you need to specify the date ggplot(data.frame(stamp = 1:20, value = 1:20), aes(x = stamp, y = value)) + geom_point() + annotate_lunarphase(date = "2020-01-01", placement = c(0.1, 0.9))library(ggplot2) library(dplyr) library(lubridate) data(bats) monitoring <- attr(bats, "monitoring") ## A lunar annotation can be added to a geom_hourglass layer ggplot(mutate(bats, YEAR = year(RECDATETIME), MONTH = month(RECDATETIME)) |> filter(YEAR == 2018, MONTH == 5), aes(x = RECDATETIME, col = SPECDESCSCI)) + geom_hourglass() + annotate_lunarphase( longitude = monitoring$longitude[[1]], latitude = monitoring$latitude[[1]], placement = 0.8) + scale_x_datetime(limits = as_datetime(c("2018-04-27", "2018-05-31"))) ## In fact, it can be added to any plot with a continuous datetime scale ggplot(data.frame(stamp = seq(as_datetime("2025-04-01 UTC"), as_datetime("2025-04-30 UTC"), length.out = 20), value = 1:20), aes(x = stamp, y = value)) + geom_point() + annotate_lunarphase() ## Moreover, you can add it to an arbitrary plot without such scales, ## but then you need to specify the date ggplot(data.frame(stamp = 1:20, value = 1:20), aes(x = stamp, y = value)) + geom_point() + annotate_lunarphase(date = "2020-01-01", placement = c(0.1, 0.9))
A dataset containing detections of audio call sequences from bats. It is a small subset of the data published by Lagerveld et al. (2023)
A data.frame with 1,037 rows and 2 columns:
RECDATETIME: datetime of the recorded bat call sequence
SPECDESCSCI: scientific species name
It also contains an attribute named monitoring which is a data.frame
containing monitoring periods at which the bat detector was active. Each
row is a monitoring period, and it holds the following columns:
start: start datetime of the monitoring period
end: end datetime of the monitoring period
time_on: time of day at which the detector is activated
during the monitoring period
time_off: time of day at which the detector is deactivated
during the monitoring period
longitude and latitude: coordinates of the detector's location
altitude: altitude in meters above sea level of the detector.
Lagerveld, S., Wilkes, T., van Puijenbroek, M.E.B., Noort, B.C.A., Geelhoed, S.C.V. Acoustic monitoring reveals spatiotemporal occurrence of Nathusius’ pipistrelle at the southern North Sea during autumn migration. Environ Monit Assess 195, 1016 (2023) https://doi.org/10.1007/s10661-023-11590-2
data("bats")data("bats")
A Cartesian coordinate system that adds sensible
guides to axes in a geom_hourglass() layer. It is added automatically
to geom_hourglass(). There is no need to explicitly add it to a ggplot,
unless you wish to tweak the coordinate system.
CoordHourglass coord_hourglass( xlim = NULL, ylim = NULL, expand = TRUE, default = FALSE, clip = "on", date_labels = "%H:%M", layer = NULL, ... )CoordHourglass coord_hourglass( xlim = NULL, ylim = NULL, expand = TRUE, default = FALSE, clip = "on", date_labels = "%H:%M", layer = NULL, ... )
xlim, ylim
|
Limits for the x and y axes. |
expand |
If |
default |
Is this the default coordinate system? If |
clip |
Should drawing be clipped to the extent of the plot panel? A
setting of |
date_labels |
Formating string for formatting the time
labels on the axis. By default it is |
layer |
This argument allows you to pass the |
... |
Arguments passed as extra |
An object of class CoordHourglass (inherits from CoordCartesian, Coord, ggproto, gg) of length 3.
Returns a ggproto object inheriting from coord_cartesian().
Pepijn de Vries
coord_hourglass()coord_hourglass()
geom_hourglass() takes a continuous datetime object, splits in in discrete dates and
time of day with stat_hourglass(). This geometry is a wrapper
to add it as a layer to a ggplot. GeomHourglass is a ggproto object inheriting from
?ggplot2::GeomPoint. It should not be used directly. Instead call geom_hourglass().
GeomHourglass geom_hourglass( mapping = NULL, data = NULL, stat = "hourglass", position = "identity", na.rm = FALSE, show.legend = NA, hour_center = 0, inherit.aes = TRUE, ... )GeomHourglass geom_hourglass( mapping = NULL, data = NULL, stat = "hourglass", position = "identity", na.rm = FALSE, show.legend = NA, hour_center = 0, inherit.aes = TRUE, ... )
mapping |
Set of aesthetic mappings created by |
data |
The data to be displayed in this layer. If |
stat |
Can be used to overwrite the default connection between |
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?
|
hour_center |
The hour at which the time of day is centred. Default is 0, meaning midnight. -12 centres around noon of the preceding day, +12 centres around noon of the next day. |
inherit.aes |
If |
... |
Arguments passed to geometry. |
An object of class GeomHourglass (inherits from GeomPoint, Geom, ggproto, gg) of length 3.
Returns a ggplot2::layer() which can be added to a ggplot2::ggplot()
Pepijn de Vries
library(ggplot2) data(bats) monitoring <- attr(bats, "monitoring") ggplot(subset(bats, format(RECDATETIME, "%Y") == "2019"), aes(x = RECDATETIME, col = SPECDESCSCI)) + geom_hourglass() ggplot(dplyr::mutate(bats, YEAR = format(RECDATETIME, "%Y")), aes(x = RECDATETIME, col = SPECDESCSCI)) + geom_hourglass() + facet_wrap(~YEAR, scales = "free_x")library(ggplot2) data(bats) monitoring <- attr(bats, "monitoring") ggplot(subset(bats, format(RECDATETIME, "%Y") == "2019"), aes(x = RECDATETIME, col = SPECDESCSCI)) + geom_hourglass() ggplot(dplyr::mutate(bats, YEAR = format(RECDATETIME, "%Y")), aes(x = RECDATETIME, col = SPECDESCSCI)) + geom_hourglass() + facet_wrap(~YEAR, scales = "free_x")
Split a datetime object in a date component (get_date()) and
time of day (get_hour()) component, centred around a specific
hour of the day. They are used by stat_hourglass().
get_hour(x, hour_center = 0, ...) get_date(x, hour_center = 0, ...)get_hour(x, hour_center = 0, ...) get_date(x, hour_center = 0, ...)
x |
A datetime object (e.g., |
hour_center |
The hour at which the time of day is centred. Default is 0, meaning midnight. -12 centres around noon of the preceding day, +12 centres around noon of the next day. |
... |
Ignored |
Returns a period (lubridate::as.period()) in case of get_hour().
Returns a datetime object in case of get_date()
Pepijn de Vries
my_datetime <- as.POSIXct("2020-02-02 02:20:02 UTC", tz = "UTC") get_hour(my_datetime) get_hour(my_datetime, -12) get_date(my_datetime) get_date(my_datetime, -12) ## This will return the original `my_date` get_date(my_datetime) + get_hour(my_datetime) ## This will too get_date(my_datetime, -12) + get_hour(my_datetime, -12)my_datetime <- as.POSIXct("2020-02-02 02:20:02 UTC", tz = "UTC") get_hour(my_datetime) get_hour(my_datetime, -12) get_date(my_datetime) get_date(my_datetime, -12) ## This will return the original `my_date` get_date(my_datetime) + get_hour(my_datetime) ## This will too get_date(my_datetime, -12) + get_hour(my_datetime, -12)
Function that calculates coordinates of a polygon representing the shape of the illuminated fraction of the moon, as observed from Earth. The shape has a radius of 1 and is centred around (0, 0). It does not consider lunar eclipses.
lunar_phase_polygon(date, longitude, latitude, n = 100)lunar_phase_polygon(date, longitude, latitude, n = 100)
date |
A datetime object used to calculate the illuminated fraction of the moon |
longitude, latitude
|
Used to calculate zenith angle. This will result in a more accurate shape of the moon as observed at the specified location. |
n |
Number of coordinates in the returned polygon shape (should be even). |
Returns a data.frame with coordinates of a polygon representing
the shape of the illuminated fraction of the moon.
Pepijn de Vries
disc_illum <- lunar_phase_polygon(as.POSIXct("2025-04-01")) plot(NA, NA, xlim = c(-1,1), ylim = c(-1, 1), asp = 1, xlab = "x coord", ylab = "y coord") polygon(disc_illum$x, disc_illum$y, col = "white") disc_illum <- lunar_phase_polygon(as.POSIXct("2025-04-01"), 5, 50) plot(NA, NA, xlim = c(-1,1), ylim = c(-1, 1), asp = 1, xlab = "x coord", ylab = "y coord") polygon(disc_illum$x, disc_illum$y, col = "white")disc_illum <- lunar_phase_polygon(as.POSIXct("2025-04-01")) plot(NA, NA, xlim = c(-1,1), ylim = c(-1, 1), asp = 1, xlab = "x coord", ylab = "y coord") polygon(disc_illum$x, disc_illum$y, col = "white") disc_illum <- lunar_phase_polygon(as.POSIXct("2025-04-01"), 5, 50) plot(NA, NA, xlim = c(-1,1), ylim = c(-1, 1), asp = 1, xlab = "x coord", ylab = "y coord") polygon(disc_illum$x, disc_illum$y, col = "white")
stat function to wrangle data for geom_hourglass.Splits mapped x or y aesthetic from a continuous datetime into
discrete date values on the mapped axis. The hour of day is mapped to
the opposite axis.
StatHourglass stat_hourglass( mapping = NULL, data = NULL, geom = "hourglass", position = "identity", show.legend = NA, inherit.aes = TRUE, hour_center = 0, na.rm = FALSE, ... )StatHourglass stat_hourglass( mapping = NULL, data = NULL, geom = "hourglass", position = "identity", show.legend = NA, inherit.aes = TRUE, hour_center = 0, na.rm = FALSE, ... )
mapping |
Set of aesthetic mappings created by |
data |
The data to be displayed in this layer. If |
geom |
Can be used to overwrite the default connection between |
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
|
show.legend |
logical. Should this layer be included in the legends?
|
inherit.aes |
If |
hour_center |
The hour at which the time of day is centred. Default is 0, meaning midnight. -12 centres around noon of the preceding day, +12 centres around noon of the next day. |
na.rm |
If |
... |
Arguments passed as extra |
An object of class StatHourglass (inherits from Stat, ggproto, gg) of length 7.
Returns a ggplot2::layer() which can be added to a ggplot2::ggplot()
Pepijn de Vries
stat_hourglass()stat_hourglass()
Function to check if a datetime object potentially uses daylight
saving time. It is not the same as lubridate::dst(), which will
determine if daylight saving time is set for the requested date.
uses_dst(x)uses_dst(x)
x |
A datetime object. |
Returns a logical value indicating of the time zone
used by the datetime object potentially uses daylight saving time.
Pepijn de Vries
uses_dst(as.POSIXct("2020-03-29 02:00:00 CET", tz = "CET")) uses_dst(as.POSIXct("2020-03-29 02:00:00 UTC", tz = "UTC"))uses_dst(as.POSIXct("2020-03-29 02:00:00 CET", tz = "CET")) uses_dst(as.POSIXct("2020-03-29 02:00:00 UTC", tz = "UTC"))