Title: | Core Functionality for Environmental Time Series |
---|---|
Description: | Utility functions for working with environmental time series data from known locations. The compact data model is structured as a list with two dataframes. A 'meta' dataframe contains spatial and measuring device metadata associated with deployments at known locations. A 'data' dataframe contains a 'datetime' column followed by columns of measurements associated with each "device-deployment". Ephemerides calculations are based on code originally found in NOAA's "Solar Calculator" <https://gml.noaa.gov/grad/solcalc/>. |
Authors: | Jonathan Callahan [aut, cre], Hans Martin [ctb], Eli Grosman [ctb], Roger Bivand [ctb], Sebastian Luque [ctb] |
Maintainer: | Jonathan Callahan <[email protected]> |
License: | GPL-3 |
Version: | 0.3.0 |
Built: | 2025-02-01 04:13:13 UTC |
Source: | https://github.com/mazamascience/mazamatimeseries |
The Camp_Fire
dataset provides a quickly loadable
version of a mts_monitor object for practicing and code examples.
Camp_Fire
Camp_Fire
A mts object with 360 rows and 134 columns of data.
The 2018 Camp Fire was the deadliest and most destructive wildfire in California's history, and the most expensive natural disaster in the world in 2018 in terms of insured losses. The fire caused at least 85 civilian fatalities and injured 12 civilians and five firefighters. It covered an area of 153,336 acres and destroyed more than 18,000 structures, most with the first 4 hours. Smoke from the fire resulted in the worst air pollution ever for the San Francisco Bay Area and Sacramento Valley.
This dataset was was generated on 2022-10-12 by running:
library(AirMonitor) Camp_Fire <- monitor_loadAnnual(2018) %>% monitor_filter(stateCode == 'CA') %>% monitor_filterDate( startdate = 20181108, enddate = 20181123, timezone = "America/Los_Angeles" ) %>% monitor_dropEmpty() save(Camp_Fire, file = "data/Camp_Fire.rda")
The Carmel_Valley
dataset provides a quickly loadable
version of a single-sensor mts_monitor object for practicing and code
examples.
Carmel_Valley
Carmel_Valley
An mts object with 600 rows and 2 columns of data.
In August of 2016, the Soberanes fire in California burned along the Big Sur coast. It was at the time the most expensive wildfire in US history. This dataset contains PM2.5 monitoring data for the monitor in Carmel Valley which shows heavy smoke as well as strong diurnal cycles associated with sea breezes. Data are stored as an mts object and are used in some examples in the package documentation.
This dataset was generated on 2022-10-12 by running:
library(AirMonitor) Carmel_Valley <- airnow_loadAnnual(2016) %>% monitor_filterMeta(deviceDeploymentID == "a9572a904a4ed46d_840060530002") %>% monitor_filterDate(20160722, 20160815) save(Carmel_Valley, file = "data/Carmel_Valley.rda")
The example_mts
dataset provides a quickly loadable
version of an mts object for practicing and code examples.
This dataset was was generated on 2021-10-07 by running:
library(AirSensor) communities <- c("Alhambra/Monterey Park", "El Monte") example_mts <- example_sensor_scaqmd %>% sensor_filterMeta(communityRegion %in% communities) # Add required "locationName" example_mts$meta$locationName <- example_mts$meta$siteName save(example_mts, file = "data/example_mts.rda")
example_mts
example_mts
An mts object composed of "meta" and "data" dataframes.
The example_raws
dataset provides a quickly loadable
example of the data generated by the **RAWSmet** package. This data is a
sts
object containing hourly measurements from a RAWS weather station
in Saddle Mountain, WA, between July 2002 and December 2017.
This dataset was was generated on 2022-02-17 by running:
library(RAWSmet) setRawsDataDir("~/Data/RAWS") example_raws <- cefa_load(nwsID = "452701") %>% raws_filterDate(20160701, 20161001) save(example_raws, file = "data/example_raws.rda")
example_raws
example_raws
An sts object composed of "meta" and "data" dataframes.
The example_sts
dataset provides a quickly loadable
version of an sts object for practicing and code examples.
This dataset was was generated on 2021-01-08 by running:
library(AirSensor) example_sts <- example_pat example_sts$meta$elevation <- as.numeric(NA) example_sts$meta$locationName <- example_sts$meta$label save(example_sts, file = "data/example_sts.rda")
example_sts
example_sts
An sts object composed of "meta" and "data" dataframes.
Utility functions for working with environmental time series data from known locations. The compact data model is structured as a list with two dataframes. A meta' dataframe contains spatial and measuring device metadata associated with deployments at known locations. A 'data' dataframe contains a 'datetime' column followed by columns of measurements associated with each "device-deployment".
The variable(s) in ...
are used to specify columns of
mts$meta
to use for ordering. Under the hood, this
function uses arrange
on mts$meta
and then
reorders mts$data
to match.
mts_arrange(mts, ...)
mts_arrange(mts, ...)
mts |
mts object. |
... |
variables in |
A reorderd version of the incoming mts time series object.
(A list with meta
and data
dataframes.)
library(MazamaTimeSeries) example_mts$meta$latitude[1:10] # Filter for all labels with "SCSH" byElevation <- example_mts %>% mts_arrange(latitude) byElevation$meta$latitude[1:10]
library(MazamaTimeSeries) example_mts$meta$latitude[1:10] # Filter for all labels with "SCSH" byElevation <- example_mts %>% mts_arrange(latitude) byElevation$meta$latitude[1:10]
Checks on the validity of an mts object. If any test fails, this function will stop with a warning message.
mts_check(mts)
mts_check(mts)
mts |
mts object. |
Returns TRUE
invisibly if the mts object is valid.
library(MazamaTimeSeries) sts_check(example_mts) # This would throw an error if ( FALSE ) { broken_mts <- example_mts names(broken_mts) <- c('meta', 'bop') sts_check(broken_mts) }
library(MazamaTimeSeries) sts_check(example_mts) # This would throw an error if ( FALSE ) { broken_mts <- example_mts names(broken_mts) <- c('meta', 'bop') sts_check(broken_mts) }
Collapses data from all time series in mts
into a
single-time series mts object using the function provided in the
FUN
argument. The single-time series result will be located at the mean
longitude and latitude unless longitude
and latitude
are specified.
Any columns of mts$meta
that are constant across all records will be
retained in the returned mts$meta
.
The core metadata associated with this location (e.g.
countryCode, stateCode, timezone, ...
) will be determined from
the most common (or average) value found in mts$meta
. This will be
a reasonable assumption for the vast majority of intended use cases where
data from multiple devices in close proximity are averaged together.
mts_collapse( mts, longitude = NULL, latitude = NULL, deviceID = "generatedID", FUN = mean, na.rm = TRUE, ... )
mts_collapse( mts, longitude = NULL, latitude = NULL, deviceID = "generatedID", FUN = mean, na.rm = TRUE, ... )
mts |
mts object. |
longitude |
Longitude of the collapsed time series. |
latitude |
Latitude of the collapsed time series. |
deviceID |
Device identifier for the collapsed time series. |
FUN |
Function used to collapse multiple time series. |
na.rm |
Logical specifying whether NA values should be ignored when FUN is applied. |
... |
additional arguments to be passed on to the |
An mts time series object representing a single time series.
(A list with meta
and data
dataframes.)
After FUN
is applied, values of +/-Inf
and NaN
are
converted to NA
. This is a convenience for the common case where
FUN = min/max
or FUN = mean
and some of the time steps have all
missing values. See the R documentation for min
for an explanation.
library(MazamaTimeSeries) mon <- mts_collapse( mts = example_mts, deviceID = "example_ID" ) # mon$data now only has 2 columns names(mon$data) plot(mon$data, type = 'b', main = mon$meta$deviceID)
library(MazamaTimeSeries) mon <- mts_collapse( mts = example_mts, deviceID = "example_ID" ) # mon$data now only has 2 columns names(mon$data) plot(mon$data, type = 'b', main = mon$meta$deviceID)
Create a combined mts from any number of mts
objects or from a list of mts objects. The resulting mts
object with contain all deviceDeploymentIDs
found in any incoming
mts and will have a regular time axis covering the the entire range
of incoming data.
If incoming time ranges are non-contiguous, the resulting mts will
have gaps filled with NA
values.
An error is generated if the incoming mts objects have
non-identical metadata for the same deviceDeploymentID
unless
replaceMeta = TRUE
.
mts_combine( ..., replaceMeta = FALSE, overlapStrategy = c("replace all", "replace na") )
mts_combine( ..., replaceMeta = FALSE, overlapStrategy = c("replace all", "replace na") )
... |
Any number of valid mts objects. |
replaceMeta |
Logical specifying whether to allow replacement of
metadata associated with |
overlapStrategy |
Strategy to use when data found in time series overlaps. |
An mts time series object containing all time series found
in the incoming mts
objects.
(A list with meta
and data
dataframes.)
Data for any deviceDeploymentIDs
shared among mts
objects are combined with a "later is better" sensibility where any
data overlaps exist. To handle this, incoming mts objects are first
split into "shared" and "unshared" parts.
Any "shared" parts are ordered based on the
time stamp of their last record. Then dplyr::distinct()
is used to
remove records with duplicate datetime
fields.
With overlapStrategy = "replace all"
, any data records found
in "later" mts objects are preferentially retained before the "shared"
data are finally reordered by ascending datetime
.
With overlapStrategy = "replace missing"
, only missing values in "earlier"
mts objects are replaced with data records from "later" time series.
The final step is combining the "shared" and "unshared" parts and placing them on a uniform time axis.
library(MazamaTimeSeries) ids1 <- example_mts$meta$deviceDeploymentID[1:5] ids2 <- example_mts$meta$deviceDeploymentID[4:6] ids3 <- example_mts$meta$deviceDeploymentID[8:10] mts1 <- example_mts %>% mts_filterMeta(deviceDeploymentID %in% ids1) %>% mts_filterDate(20190701, 20190703) mts2 <- example_mts %>% mts_filterMeta(deviceDeploymentID %in% ids2) %>% mts_filterDate(20190704, 20190706) mts3 <- example_mts %>% mts_filterMeta(deviceDeploymentID %in% ids3) %>% mts_filterDate(20190705, 20190708) mts <- mts_combine(mts1, mts2, mts3) # Should have 1:6 + 8:10 = 9 meta records and the full date range nrow(mts$meta) range(mts$data$datetime)
library(MazamaTimeSeries) ids1 <- example_mts$meta$deviceDeploymentID[1:5] ids2 <- example_mts$meta$deviceDeploymentID[4:6] ids3 <- example_mts$meta$deviceDeploymentID[8:10] mts1 <- example_mts %>% mts_filterMeta(deviceDeploymentID %in% ids1) %>% mts_filterDate(20190701, 20190703) mts2 <- example_mts %>% mts_filterMeta(deviceDeploymentID %in% ids2) %>% mts_filterDate(20190704, 20190706) mts3 <- example_mts %>% mts_filterMeta(deviceDeploymentID %in% ids3) %>% mts_filterDate(20190705, 20190708) mts <- mts_combine(mts1, mts2, mts3) # Should have 1:6 + 8:10 = 9 meta records and the full date range nrow(mts$meta) range(mts$data$datetime)
mts$data
This function is primarily for internal use.
Two successive steps are used to guarantee that the
datetime
axis contains no repeated values:
remove any duplicate records
guarantee that rows are in datetime
order
mts_distinct(mts)
mts_distinct(mts)
mts |
mts object |
An mts object where each record is associated with a unique
time.
(A list with meta
and data
dataframes.)
These functions are convenient wrappers for extracting the dataframes that
comprise an mts object. These functions are designed to be useful when
manipulating data in a pipeline chain using %>%
.
mts_extractData(mts)
is equivalent to mts$data
.
mts_extractMeta(mts)
is equivalent to mts$meta
.
mts_extractData(mts) mts_extractMeta(mts)
mts_extractData(mts) mts_extractMeta(mts)
mts |
mts object to extract dataframe from. |
A dataframe from the mts object.
A generalized data filter for mts objects to
choose rows/cases where conditions are true. Multiple conditions may be
combined with &
or separated by a comma. Only rows where the condition
evaluates to TRUE are kept. Rows where the condition evaluates to NA
are dropped.
mts_filterData(mts, ...)
mts_filterData(mts, ...)
mts |
mts object. |
... |
Logical predicates defined in terms of the variables in
|
A subset of the incoming mts time series object.
(A list with meta
and data
dataframes.)
Filtering is done on variables in mts$data
and results in an
incomplete and irregular time axis.
library(MazamaTimeSeries) # Are there any times when data exceeded 150? sapply(example_mts$data, function(x) { any(x > 150, na.rm = TRUE) }) # Show all times where da4cadd2d6ea5302_4686 > 150 example_mts %>% mts_filterData(da4cadd2d6ea5302_4686 > 150) %>% mts_extractData() %>% dplyr::pull(datetime)
library(MazamaTimeSeries) # Are there any times when data exceeded 150? sapply(example_mts$data, function(x) { any(x > 150, na.rm = TRUE) }) # Show all times where da4cadd2d6ea5302_4686 > 150 example_mts %>% mts_filterData(da4cadd2d6ea5302_4686 > 150) %>% mts_extractData() %>% dplyr::pull(datetime)
Subsets an mts object by date. This function
always filters to day-boundaries. For sub-day filtering, use
mts_setTimeAxis()
.
Dates can be anything that is understood by MazamaCoreUtils::parseDatetime()
including either of the following recommended formats:
"YYYYmmdd"
"YYYY-mm-dd"
Timezone determination precedence assumes that if you are passing in
POSIXct
values then you know what you are doing:
get timezone from startdate
if it is POSIXct
use passed in timezone
get timezone from mts
mts_filterDate( mts = NULL, startdate = NULL, enddate = NULL, timezone = NULL, unit = "sec", ceilingStart = FALSE, ceilingEnd = FALSE )
mts_filterDate( mts = NULL, startdate = NULL, enddate = NULL, timezone = NULL, unit = "sec", ceilingStart = FALSE, ceilingEnd = FALSE )
mts |
mts object. |
startdate |
Desired start date (ISO 8601). |
enddate |
Desired end date (ISO 8601). |
timezone |
Olson timezone used to interpret dates. |
unit |
Units used to determine time at end-of-day. |
ceilingStart |
Logical instruction to apply
|
ceilingEnd |
Logical instruction to apply
|
A subset of the incoming mts time series object.
(A list with meta
and data
dataframes.)
The returned data will run from the beginning of startdate
until
the beginning of enddate
– i.e. no values associated
with enddate
will be returned. The exception being when
enddate
is less than 24 hours after startdate
. In that case, a
single day is returned.
library(MazamaTimeSeries) example_mts %>% mts_filterDate( startdate = 20190703, enddate = 20190706 ) %>% mts_extractData() %>% dplyr::pull(datetime) %>% range()
library(MazamaTimeSeries) example_mts %>% mts_filterDate( startdate = 20190703, enddate = 20190706 ) %>% mts_extractData() %>% dplyr::pull(datetime) %>% range()
DEPRECATED -- use mts_setTimeAxis
.
Subsets an mts
object by datetime. This function
allows for sub-day filtering as opposed to mts_filterDate()
which
always filters to day-boundaries. Both the startdate
and the
enddate
will be included in the subset.
Datetimes can be anything that is understood by
MazamaCoreUtils::parseDatetime()
. For non-POSIXct
values,
the recommended format is "YYYY-mm-dd HH:MM:SS"
.
Timezone determination precedence assumes that if you are passing in
POSIXct
values then you know what you are doing:
get timezone from startdate
if it is POSIXct
use passed in timezone
get timezone from mts
mts_filterDatetime( mts = NULL, startdate = NULL, enddate = NULL, timezone = NULL, unit = "sec", ceilingStart = FALSE, ceilingEnd = FALSE, includeEnd = FALSE )
mts_filterDatetime( mts = NULL, startdate = NULL, enddate = NULL, timezone = NULL, unit = "sec", ceilingStart = FALSE, ceilingEnd = FALSE, includeEnd = FALSE )
mts |
mts object. |
startdate |
Desired start datetime (ISO 8601). |
enddate |
Desired end datetime (ISO 8601). |
timezone |
Olson timezone used to interpret dates. |
unit |
Datetimes will be rounded to the nearest |
ceilingStart |
Logical instruction to apply
|
ceilingEnd |
Logical instruction to apply
|
includeEnd |
Logical specifying that records associated with |
A subset of the incoming mts time series object.
(A list with meta
and data
dataframes.)
This function is deprecated as of MazamaTimeSeries 0.2.15. Please use mts_setTimeAxis to shorten or lengthen the time axis of an mts object.
A generalized metadata filter for mts objects to
choose rows/cases where conditions are true. Multiple conditions are
combined with &
or separated by a comma. Only rows where the condition
evaluates to TRUE are kept. Rows where the condition evaluates to FALSE or
NA
are dropped.
If an empty mts object is passed in, it is immediately returned, allowing for multiple filtering steps to be piped together and only checking for an empty mts object at the end of the pipeline.
mts_filterMeta(mts, ...)
mts_filterMeta(mts, ...)
mts |
mts object. |
... |
Logical predicates defined in terms of the variables in
|
A subset of the incoming mts time series object.
(A list with meta
and data
dataframes.)
Filtering is done on variables in mts$meta
.
library(MazamaTimeSeries) # Filter for all labels with "SCSH" scap <- example_mts %>% mts_filterMeta(communityRegion == "El Monte") dplyr::select(scap$meta, ID, label, longitude, latitude, communityRegion) head(scap$data)
library(MazamaTimeSeries) # Filter for all labels with "SCSH" scap <- example_mts %>% mts_filterMeta(communityRegion == "El Monte") dplyr::select(scap$meta, ID, label, longitude, latitude, communityRegion) head(scap$data)
This function uses the [geodist] package to return the distances (meters)
between mts
locations
and a location of interest. These distances can be used to create a
mask identifying monitors within a certain radius of the location of interest.
mts_getDistance( mts = NULL, longitude = NULL, latitude = NULL, measure = c("geodesic", "haversine", "vincenty", "cheap") )
mts_getDistance( mts = NULL, longitude = NULL, latitude = NULL, measure = c("geodesic", "haversine", "vincenty", "cheap") )
mts |
mts object. |
longitude |
Longitude of the location of interest. |
latitude |
Latitude of the location of interest. |
measure |
One of "geodesic", "haversine", "vincenty" or "cheap" |
Vector of of distances (meters) named by deviceDeploymentID
.
The measure "cheap"
may be used to speed things up depending on
the spatial scale being considered. Distances calculated with
measure = "cheap"
will vary by a few meters compared with those
calculated using measure = "geodesic"
.
library(MazamaTimeSeries) # Garfield Medical Center in LA longitude <- -118.12321 latitude <- 34.06775 distances <- mts_getDistance( mts = example_mts, longitude = longitude, latitude = latitude ) # Which sensors are within 1000 meters of Garfield Med Ctr? distances[distances <= 1000]
library(MazamaTimeSeries) # Garfield Medical Center in LA longitude <- -118.12321 latitude <- 34.06775 distances <- mts_getDistance( mts = example_mts, longitude = longitude, latitude = latitude ) # Which sensors are within 1000 meters of Garfield Med Ctr? distances[distances <= 1000]
Convenience function for nrow(mts$data) == 0
.
This makes for more readable code in functions that need to test for this.
mts_isEmpty(mts)
mts_isEmpty(mts)
mts |
mts object |
TRUE
if no data exist in mts
, FALSE
otherwise.
library(MazamaTimeSeries) mts_isEmpty(example_mts)
library(MazamaTimeSeries) mts_isEmpty(example_mts)
The mts
is checked for the presence of core
meta
and data
columns.
Core meta
columns include:
deviceDeploymentID
– unique identifier (see MazmaLocationUtils)
deviceID
– device identifier
locationID
– location identifier (see MazmaLocationUtils)
locationName
– English language name
longitude
– decimal degrees E
latitude
– decimal degrees N
elevation
– elevation of station in m
countryCode
– ISO 3166-1 alpha-2
stateCode
– ISO 3166-2 alpha-2
timezone
– Olson time zone
Core data
columns include:
datetime
– measurement time (UTC)
mts_isValid(mts = NULL, verbose = FALSE)
mts_isValid(mts = NULL, verbose = FALSE)
mts |
mts object |
verbose |
Logical specifying whether to produce detailed warning messages. |
Invisibly returns TRUE
if mts
has the correct structure,
FALSE
otherwise.
library(MazamaTimeSeries) print(mts_isValid(example_mts))
library(MazamaTimeSeries) print(mts_isValid(example_mts))
This function acts similarly to dplyr::pull()
working on
mts$meta
or mts$data
. Data are returned as a simple array.
Data are pulled from whichever dataframe contains var
.
mts_pull(mts = NULL, var = NULL)
mts_pull(mts = NULL, var = NULL)
mts |
mts object. |
var |
A variable name found in the |
An array of values.
library(MazamaTimeSeries) # Metadata example_mts %>% mts_pull("communityRegion") %>% table() %>% sort(decreasing = TRUE) # Data for a specific ID example_mts %>% mts_pull("da4cadd2d6ea5302_4686")
library(MazamaTimeSeries) # Metadata example_mts %>% mts_pull("communityRegion") %>% table() %>% sort(decreasing = TRUE) # Data for a specific ID example_mts %>% mts_pull("da4cadd2d6ea5302_4686")
Reduce the number of records (timesteps) in the data
dataframe of the incoming mts
through random sampling.
mts_sample( mts = NULL, sampleSize = 5000, seed = NULL, keepOutliers = FALSE, width = 5, thresholdMin = 3 )
mts_sample( mts = NULL, sampleSize = 5000, seed = NULL, keepOutliers = FALSE, width = 5, thresholdMin = 3 )
mts |
mts object. |
sampleSize |
Non-negative integer giving the number of rows to choose. |
seed |
Integer passed to |
keepOutliers |
Logical specifying a graphics focused sampling algorithm that retains outliers (see Details). |
width |
Integer width of the rolling window used for outlier detection. |
thresholdMin |
Numeric threshold for outlier detection. |
When keepOutliers = FALSE
, random sampling is used to provide
a statistically relevant subsample of the data.
A subset of the given mts object.
An mts time series object with fewer timesteps.
(A list with meta
and data
dataframes.)
When keepOutliers = TRUE
, a customized sampling algorithm is used that
attempts to create subsets for use in plotting that create plots that are
visually identical to plots using all data. This is accomplished by
preserving outliers and only sampling data in regions where overplotting
is expected.
The process is as follows:
find outliers using MazamaRollUtils::findOutliers()
create a subset consisting of only outliers
sample the remaining data
merge the outliers and sampled data
This algorithm works best when the mts object has only one or two timeseries.
The width
and thresholdMin
parameters determine the number of
outliers detected. For hourly data, a width
of 5 and a thresholdMin
of 3 or 4 seem to find many visually obvious outliers.
Users attempting to optimize plotting speed for lengthy time series are
encouraged to experiment with these two parameters along with
sampleSize
and review the results visually.
See MazamaRollUtils::findOutliers()
.
This function acts similarly to dplyr::select()
working on
mts$data
. The returned mts object will contain only those
time series identified by deviceDeploymentID
in the order specified.
This can be used the specify a preferred order and is helpful when using faceted plot functions based on ggplot such as those found in the AirMonitorPlots package.
mts_select(mts = NULL, deviceDeploymentID = NULL)
mts_select(mts = NULL, deviceDeploymentID = NULL)
mts |
mts object. |
deviceDeploymentID |
Vector of timeseries unique identifiers. |
A reordered (subset) of the incoming mts time series object.
(A list with meta
and data
dataframes.)
library(MazamaTimeSeries) # Filter for "El Monte" El_Monte <- example_mts %>% mts_filterMeta(communityRegion == "El Monte") ids <- El_Monte$meta$deviceDeploymentID rev_ids <- rev(ids) print(ids) print(rev_ids) rev_El_Monte <- example_mts %>% mts_select(rev_ids) print(rev_El_Monte$meta$deviceDeploymentID)
library(MazamaTimeSeries) # Filter for "El Monte" El_Monte <- example_mts %>% mts_filterMeta(communityRegion == "El Monte") ids <- El_Monte$meta$deviceDeploymentID rev_ids <- rev(ids) print(ids) print(rev_ids) rev_El_Monte <- example_mts %>% mts_select(rev_ids) print(rev_El_Monte$meta$deviceDeploymentID)
Subsetting of mts
acts similarly to tidyselect::where()
working on
mts$data
. The returned mts object will contain only
those time series where FUN
applied to the time series data returns TRUE
.
mts_selectWhere(mts, FUN)
mts_selectWhere(mts, FUN)
mts |
mts object. |
FUN |
A function applied to time series data that returns TRUE or FALSE. |
A subset of the incoming mts object. (A list with
meta
and data
dataframes.)
library(MazamaTimeSeries) # Show all Camp_Fire locations Camp_Fire$meta$locationName # Set a threshold threshold <- 500 # Find time series with data at or above this threshold worst_sites <- Camp_Fire %>% mts_selectWhere( function(x) { any(x >= threshold, na.rm = TRUE) } ) # Show the worst locations worst_sites$meta$locationName
library(MazamaTimeSeries) # Show all Camp_Fire locations Camp_Fire$meta$locationName # Set a threshold threshold <- 500 # Find time series with data at or above this threshold worst_sites <- Camp_Fire %>% mts_selectWhere( function(x) { any(x >= threshold, na.rm = TRUE) } ) # Show the worst locations worst_sites$meta$locationName
Extends or contracts the time range of an mts object by adding/removing time steps at the start and end and filling any new time steps with missing values. The resulting time axis is guaranteed to be a regular, hourly axis with no gaps using the same timezone as the incoming mts object. This is useful when you want to place separate mts objects on the same time axis for plotting.
Dates can be anything that is understood by MazamaCoreUtils::parseDatetime()
including either of the following recommended formats:
"YYYYmmdd"
"YYYY-mm-dd"
Timezone determination precedence assumes that if you are passing in
POSIXct
values then you know what you are doing:
get timezone from startdate
if it is POSIXct
use passed in timezone
get timezone from mts
If either startdate
or enddate
is missing, the start or end of
the timeseries in mts
will be used.
If neither startdate
nor enddate
is a POSIXct
value
AND no timezone
is supplied, the timezone will be inferred from
the most common timezone found in mts
.
mts_setTimeAxis(mts = NULL, startdate = NULL, enddate = NULL, timezone = NULL)
mts_setTimeAxis(mts = NULL, startdate = NULL, enddate = NULL, timezone = NULL)
mts |
mts object. |
startdate |
Desired start date (ISO 8601). |
enddate |
Desired end date (ISO 8601). |
timezone |
Olson timezone used to interpret |
The incoming mts time series object defined on a new time axis.
(A list with meta
and data
dataframes.)
library(MazamaTimeSeries) # Default range range(example_mts$data$datetime) # One-sided extend with user specified timezone example_mts %>% mts_setTimeAxis(enddate = 20190815, timezone = "UTC") %>% mts_extractData() %>% dplyr::pull(datetime) %>% range() # Two-sided extend with user specified timezone example_mts %>% mts_setTimeAxis(20190615, 20190815, timezone = "UTC") %>% mts_extractData() %>% dplyr::pull(datetime) %>% range() # Two-sided extend without timezone (uses timezone from mts$meta$timezone) example_mts %>% mts_setTimeAxis(20190615, 20190815) %>% mts_extractData() %>% dplyr::pull(datetime) %>% range()
library(MazamaTimeSeries) # Default range range(example_mts$data$datetime) # One-sided extend with user specified timezone example_mts %>% mts_setTimeAxis(enddate = 20190815, timezone = "UTC") %>% mts_extractData() %>% dplyr::pull(datetime) %>% range() # Two-sided extend with user specified timezone example_mts %>% mts_setTimeAxis(20190615, 20190815, timezone = "UTC") %>% mts_extractData() %>% dplyr::pull(datetime) %>% range() # Two-sided extend without timezone (uses timezone from mts$meta$timezone) example_mts %>% mts_setTimeAxis(20190615, 20190815) %>% mts_extractData() %>% dplyr::pull(datetime) %>% range()
An mts object is reduced so as to contain only the first
or last n
timeseries. These functions work similarly to
dplyr::slice_head
and
dplyr::slice_tail
but apply to both dataframes in the mts object.
This is primarily useful when the mts object has been ordered by a
previous call to mts_arrange
or by some other means.
slice_head()
selects the first and slice_tail()
the last timeseries
in the object.
mts_slice_head(mts, n = 5) mts_slice_tail(mts, n = 5)
mts_slice_head(mts, n = 5) mts_slice_tail(mts, n = 5)
mts |
mts object. |
n |
Number of rows of |
A subset of the incoming mts time series object.
(A list with meta
and data
dataframes.)
library(MazamaTimeSeries) # Find lowest elevation sites Camp_Fire %>% mts_filterMeta(!is.na(elevation)) %>% mts_arrange(elevation) %>% mts_slice_head(n = 5) %>% mts_extractMeta() %>% dplyr::select(elevation, locationName) # Find highest elevation sites Camp_Fire %>% mts_filterMeta(!is.na(elevation)) %>% mts_arrange(elevation) %>% mts_slice_tail(n = 5) %>% mts_extractMeta() %>% dplyr::select(elevation, locationName)
library(MazamaTimeSeries) # Find lowest elevation sites Camp_Fire %>% mts_filterMeta(!is.na(elevation)) %>% mts_arrange(elevation) %>% mts_slice_head(n = 5) %>% mts_extractMeta() %>% dplyr::select(elevation, locationName) # Find highest elevation sites Camp_Fire %>% mts_filterMeta(!is.na(elevation)) %>% mts_arrange(elevation) %>% mts_slice_tail(n = 5) %>% mts_extractMeta() %>% dplyr::select(elevation, locationName)
Individual time series in mts$data
are grouped by unit
and then
summarized using FUN
.
The most typical use case is creating daily averages where each day begins at
midnight. This function interprets times using the mts$data$datetime
tzone
attribute so be sure that is set properly.
Day boundaries are calculated using the specified timezone
or, if
NULL
, the most common (hopefully only!) time zone found in
mts$meta$timezone
. Leaving timezone = NULL
, the default,
results in "local time" date filtering which is the most common use case.
mts_summarize( mts, timezone = NULL, unit = c("day", "week", "month", "year"), FUN = NULL, ..., minCount = NULL )
mts_summarize( mts, timezone = NULL, unit = c("day", "week", "month", "year"), FUN = NULL, ..., minCount = NULL )
mts |
mts object. |
timezone |
Olson timezone used to interpret dates. |
unit |
Unit used to summarize by (e.g. "day"). |
FUN |
Function used to summarize time series. |
... |
Additional arguments to be passed to |
minCount |
Minimum number of valid data records required to calculate
summaries. Time periods with fewer valid records will be assigned |
An mts time series object containing daily (or other)
statistical summaries.
(A list with meta
and data
dataframes.)
Because the returned mts object is defined on a daily axis in a
specific time zone, it is important that the incoming mts
contain
timeseries associated with a single time zone.
library(MazamaTimeSeries) daily <- mts_summarize( mts = Carmel_Valley, timezone = NULL, unit = "day", FUN = mean, na.rm = TRUE, minCount = 18 ) # Daily means head(daily$data)
library(MazamaTimeSeries) daily <- mts_summarize( mts = Carmel_Valley, timezone = NULL, unit = "day", FUN = mean, na.rm = TRUE, minCount = 18 ) # Daily means head(daily$data)
Trims the time range of an mts object by removing time steps from the start and end that contain only missing values.
mts_trim(mts = NULL)
mts_trim(mts = NULL)
mts |
mts object. |
A subset of the incoming mts time series object.
(A list with meta
and data
dataframes.)
library(MazamaTimeSeries) # Untrimmed range range(example_mts$data$datetime) # Replace the first 50 data values for all non-"datetime" columns example_mts$data[1:50, -1] <- NA # Trimmed range mts_trimmed <- mts_trim(example_mts) range(mts_trimmed$data$datetime)
library(MazamaTimeSeries) # Untrimmed range range(example_mts$data$datetime) # Replace the first 50 data values for all non-"datetime" columns example_mts$data[1:50, -1] <- NA # Trimmed range mts_trimmed <- mts_trim(example_mts) range(mts_trimmed$data$datetime)
Trims the date range of an mts object to local time date boundaries which are within the time range of the mts object. This has the effect of removing partial-day data records at the start and end of the timeseries and is useful when calculating full-day statistics.
By default, multi-day periods of all-missing data at the beginning and end
of the timeseries are removed before trimming to date boundaries. If
trimEmptyDays = FALSE
all records are retained except for partial days
beyond the first and after the last date boundary.
Day boundaries are calculated using the specified timezone
or, if
NULL
, mts$meta$timezone
. Leaving timezone = NULL
, the
default, results in "local time" date filtering which is the most
common use case.
mts_trimDate(mts = NULL, timezone = NULL, trimEmptyDays = TRUE)
mts_trimDate(mts = NULL, timezone = NULL, trimEmptyDays = TRUE)
mts |
mts object. |
timezone |
Olson timezone used to interpret dates. |
trimEmptyDays |
Logical specifying whether to remove days with no data at the beginning and end of the time range. |
A subset of the incoming mts time series object.
(A list with meta
and data
dataframes.)
library(MazamaTimeSeries) UTC_week <- mts_filterDate( example_mts, startdate = 20190703, enddate = 20190706, timezone = "UTC" ) # UTC day boundaries range(UTC_week$data$datetime) # Trim to local time day boundaries local_week <- mts_trimDate(UTC_week) range(local_week$data$datetime)
library(MazamaTimeSeries) UTC_week <- mts_filterDate( example_mts, startdate = 20190703, enddate = 20190706, timezone = "UTC" ) # UTC day boundaries range(UTC_week$data$datetime) # Trim to local time day boundaries local_week <- mts_trimDate(UTC_week) range(local_week$data$datetime)
The 'meta' dataframe found in sts and mts objects
is required to have a minimum set of information for proper functioning of
the package. The names of these columns are specified in
requiredMetaNames
and include:
deviceDeploymentID
– unique identifier (see MazmaLocationUtils)
deviceID
– device identifier
locationID
– location identifier (see MazmaLocationUtils)
locationName
– English language name
longitude
– decimal degrees E
latitude
– decimal degrees N
elevation
– elevation of station in m
countryCode
– ISO 3166-1 alpha-2
stateCode
– ISO 3166-2 alpha-2
timezone
– Olson time zone
requiredMetaNames
requiredMetaNames
A vector with 10 elements
requiredMetaNames
Checks on the validity of an sts object. If any test fails, this function will stop with a warning message.
sts_check(sts)
sts_check(sts)
sts |
sts object. |
Returns TRUE
invisibly if the sts object is valid.
library(MazamaTimeSeries) sts_check(example_sts) # This would throw an error if ( FALSE ) { broken_sts <- example_sts names(broken_sts) <- c('meta', 'bop') sts_check(broken_sts) }
library(MazamaTimeSeries) sts_check(example_sts) # This would throw an error if ( FALSE ) { broken_sts <- example_sts names(broken_sts) <- c('meta', 'bop') sts_check(broken_sts) }
Create a merged timeseries using of any number of sts objects for a single sensor. If sts objects are non-contiguous, the resulting sts will have gaps.
An error is generated if the incoming sts objects have
non-identical deviceDeploymentIDs
.
sts_combine(..., replaceMeta = FALSE)
sts_combine(..., replaceMeta = FALSE)
... |
Any number of valid SingleTimeSeries sts objects associated
with a single |
replaceMeta |
Logical specifying whether to allow replacement of metadata. |
A SingleTimeSeries sts time series object containing
records from all incoming sts
time series objects.
(A list with meta
and data
dataframes.)
Data are combined with a "later is better" sensibility where any data overlaps exist. To handle this, incoming sts objects are first split into "shared" and "unshared" parts.
Any "shared" parts are ordered based on the
time stamp of their last record. Then dplyr::distinct()
is used to
remove records with duplicate datetime
fields. Any data records found
in "later" sts objects are preferentially retained before the "shared"
data are finally reordered by ascending datetime
.
The final step is combining the "shared" and "unshared" parts.
library(MazamaTimeSeries) aug01_08 <- example_sts %>% sts_filterDate(20180801, 20180808) aug15_22 <- example_sts %>% sts_filterDate(20180815, 20180822) aug01_22 <- sts_combine(aug01_08, aug15_22) plot(aug01_22$data$datetime)
library(MazamaTimeSeries) aug01_08 <- example_sts %>% sts_filterDate(20180801, 20180808) aug15_22 <- example_sts %>% sts_filterDate(20180815, 20180822) aug01_22 <- sts_combine(aug01_08, aug15_22) plot(aug01_22$data$datetime)
sts$data
Three successive steps are used to guarantee that the
datetime
axis contains no repeated values:
remove any duplicate records
guarantee that rows are in datetime
order
average together fields for any remaining records that share the same
datetime
sts_distinct(sts)
sts_distinct(sts)
sts |
sts object |
An sts object where each record is associated with a unique
time.
(A list with meta
and data
dataframes.)
These functions are convenient wrappers for extracting the dataframes that
comprise a sts object. These functions are designed to be useful when
manipulating data in a pipeline using %>%
.
Below is a table showing equivalent operations for each function.
sts_extractData(sts)
is equivalent to sts$data
.
sts_extractMeta(sts)
is equivalent to sts$meta
.
sts_extractData(sts) sts_extractMeta(sts)
sts_extractData(sts) sts_extractMeta(sts)
sts |
sts object to extract dataframe from. |
A dataframe from the sts object.
A generalized data filter for sts objects to
choose rows/cases where conditions are true. Multiple conditions are
combined with &
or separated by a comma. Only rows where the condition
evaluates to TRUE are kept. Rows where the condition evaluates to NA
are dropped.
If an empty sts object is passed in, it is immediately returned, allowing for multiple filtering steps to be piped together and only checking for an empty sts object at the end of the pipeline.
sts_filter(sts, ...)
sts_filter(sts, ...)
sts |
sts object. |
... |
Logical predicates defined in terms of the variables in
|
A subset of the incoming sts
time series object.
(A list with meta
and data
dataframes.)
Filtering is done on values in sts$data
.
library(MazamaTimeSeries) unhealthy <- sts_filter(example_sts, pm25_A > 55.5, pm25_B > 55.5) head(unhealthy$data)
library(MazamaTimeSeries) unhealthy <- sts_filter(example_sts, pm25_A > 55.5, pm25_B > 55.5) head(unhealthy$data)
Subsets a MazamaSingleTimeseries object by date. This function
always filters to day-boundaries. For sub-day filtering, use
sts_filterDatetime()
.
Dates can be anything that is understood by MazamaCoreUtils::parseDatetime()
including either of the following recommended formats:
"YYYYmmdd"
"YYYY-mm-dd"
Timezone determination precedence assumes that if you are passing in
POSIXct
values then you know what you are doing.
get timezone from startdate
if it is POSIXct
use passed in timezone
get timezone from sts
sts_filterDate( sts = NULL, startdate = NULL, enddate = NULL, timezone = NULL, unit = "sec", ceilingStart = FALSE, ceilingEnd = FALSE )
sts_filterDate( sts = NULL, startdate = NULL, enddate = NULL, timezone = NULL, unit = "sec", ceilingStart = FALSE, ceilingEnd = FALSE )
sts |
MazamaSingleTimeseries sts object. |
startdate |
Desired start datetime (ISO 8601). |
enddate |
Desired end datetime (ISO 8601). |
timezone |
Olson timezone used to interpret dates. |
unit |
Units used to determine time at end-of-day. |
ceilingStart |
Logical instruction to apply
|
ceilingEnd |
Logical instruction to apply
|
A subset of the incoming sts time series object.
(A list with meta
and data
dataframes.)
The returned data will run from the beginning of startdate
until
the beginning of enddate
– i.e. no values associated
with enddate
will be returned. The exception being when
enddate
is less than 24 hours after startdate
. In that case, a
single day is returned.
library(MazamaTimeSeries) example_sts %>% sts_filterDate(startdate = 20180808, enddate = 20180815) %>% sts_extractData() %>% head()
library(MazamaTimeSeries) example_sts %>% sts_filterDate(startdate = 20180808, enddate = 20180815) %>% sts_extractData() %>% head()
Subsets a MazamaSingleTimeseries object by datetime. This function
allows for sub-day filtering as opposed to sts_filterDate()
which
always filters to day-boundaries.
Datetimes can be anything that is understood by
MazamaCoreUtils::parseDatetime()
. For non-POSIXct
values,
the recommended format is "YYYY-mm-dd HH:MM:SS"
.
Timezone determination precedence assumes that if you are passing in
POSIXct
values then you know what you are doing.
get timezone from startdate
if it is POSIXct
use passed in timezone
get timezone from sts
sts_filterDatetime( sts = NULL, startdate = NULL, enddate = NULL, timezone = NULL, unit = "sec", ceilingStart = FALSE, ceilingEnd = FALSE, includeEnd = FALSE )
sts_filterDatetime( sts = NULL, startdate = NULL, enddate = NULL, timezone = NULL, unit = "sec", ceilingStart = FALSE, ceilingEnd = FALSE, includeEnd = FALSE )
sts |
MazamaSingleTimeseries sts object. |
startdate |
Desired start datetime (ISO 8601). |
enddate |
Desired end datetime (ISO 8601). |
timezone |
Olson timezone used to interpret dates. |
unit |
Units used to determine time at end-of-day. |
ceilingStart |
Logical instruction to apply
|
ceilingEnd |
Logical instruction to apply
|
includeEnd |
Logical specifying that records associated with |
A subset of the incoming sts time series object.
(A list with meta
and data
dataframes.)
The returned sts
object will contain data running from the
beginning of startdate
until
the beginning of enddate
– i.e. no values associated
with enddate
will be returned. To include enddate
you can
specify includeEnd = TRUE
.
library(MazamaTimeSeries) example_sts %>% sts_filterDatetime( startdate = "2018-08-08 06:00:00", enddate = "2018-08-14 18:00:00" ) %>% sts_extractData() %>% head()
library(MazamaTimeSeries) example_sts %>% sts_filterDatetime( startdate = "2018-08-08 06:00:00", enddate = "2018-08-14 18:00:00" ) %>% sts_extractData() %>% head()
Convenience function for nrow(sts$data) == 0
.
This makes for more readable code in functions that need to test for this.
sts_isEmpty(sts)
sts_isEmpty(sts)
sts |
sts object |
TRUE
if no data exist in sts
, FALSE
otherwise.
library(MazamaTimeSeries) sts_isEmpty(example_sts)
library(MazamaTimeSeries) sts_isEmpty(example_sts)
The sts
is checked for the presence of core
meta
and data
columns.
Core meta
columns include:
deviceDeploymentID
– unique identifier (see MazmaLocationUtils)
deviceID
– device identifier
locationID
– location identifier (see MazmaLocationUtils)
locationName
– English language name
longitude
– decimal degrees E
latitude
– decimal degrees N
elevation
– elevation of station in m
countryCode
– ISO 3166-1 alpha-2
stateCode
– ISO 3166-2 alpha-2
timezone
– Olson time zone
Core data
columns include:
datetime
– measurement time (UTC)
sts_isValid(sts = NULL, verbose = FALSE)
sts_isValid(sts = NULL, verbose = FALSE)
sts |
sts object |
verbose |
Logical specifying whether to produce detailed warning messages. |
TRUE
if sts
has the correct structure,
FALSE
otherwise.
library(MazamaTimeSeries) sts_isValid(example_sts)
library(MazamaTimeSeries) sts_isValid(example_sts)
Columns of numeric data in sts$data
are grouped by unit
and then
summarized using FUN
.
Columns with non-numeric data are summarized by just picking the first
occurrence in each unit
. This preserves the utility of columns
containing repeated metadata.
The most typical use case is creating daily averages where each day begins at
midnight. Day boundaries are calculated using the specified timezone
or, if NULL
, the time zone found in sts$meta$timezone[1]
.
Leaving timezone = NULL
, the default, results in "local time" date
filtering which is the most common use case.
sts_summarize( sts, timezone = NULL, unit = c("day", "week", "month", "year"), FUN = NULL, ..., minCount = NULL )
sts_summarize( sts, timezone = NULL, unit = c("day", "week", "month", "year"), FUN = NULL, ..., minCount = NULL )
sts |
sts object. |
timezone |
Olson timezone used to interpret dates. |
unit |
Unit used to summarize by (e.g. "day"). |
FUN |
Function used to summarize time series. |
... |
Additional arguments to be passed to |
minCount |
Minimum number of valid data records required to calculate
summaries. Time periods with fewer valid records will be assigned |
An sts time series object containing daily (or other)
statistical summaries.
(A list with meta
and data
dataframes.)
Trims the date range of a sts object to local time date boundaries which are within the range of data. This has the effect of removing partial-day data records at the start and end of the timeseries and is useful when calculating full-day statistics.
Day boundaries are calculated using the specified timezone
or, if
NULL
, from sts$meta$timezone
.
sts_trimDate(sts = NULL, timezone = NULL)
sts_trimDate(sts = NULL, timezone = NULL)
sts |
SingleTimeSeries sts object. |
timezone |
Olson timezone used to interpret dates. |
A subset of the incoming sts time series object.
(A list with meta
and data
dataframes.)
library(MazamaTimeSeries) UTC_week <- sts_filterDate( example_sts, startdate = 20180808, enddate = 20180815, timezone = "UTC" ) # UTC day boundaries head(UTC_week$data) # Trim to local time day boundaries local_week <- sts_trimDate(UTC_week) head(local_week$data)
library(MazamaTimeSeries) UTC_week <- sts_filterDate( example_sts, startdate = 20180808, enddate = 20180815, timezone = "UTC" ) # UTC day boundaries head(UTC_week$data) # Trim to local time day boundaries local_week <- sts_trimDate(UTC_week) head(local_week$data)
Calculate the local time at the target location, as well as sunrise, sunset and solar noon times, and create several temporal masks.
The returned dataframe will have as many rows as the length of the incoming
UTC time
vector and will contain the following columns:
localStdTime_UTC
– UTC representation of local standard time
daylightSavings
– logical mask = TRUE if daylight savings is in effect
localTime
– local clock time
sunrise
– time of sunrise on each localTime day
sunset
– time of sunset on each localTime day
solarnoon
– time of solar noon on each localTime day
day
– logical mask = TRUE between sunrise and sunset
morning
– logical mask = TRUE between sunrise and solarnoon
afternoon
– logical mask = TRUE between solarnoon and sunset
night
– logical mask = opposite of day
timeInfo(time = NULL, longitude = NULL, latitude = NULL, timezone = NULL)
timeInfo(time = NULL, longitude = NULL, latitude = NULL, timezone = NULL)
time |
POSIXct vector with specified timezone, |
longitude |
Longitude of the location of interest. |
latitude |
Latitude of the location of interest. |
timezone |
Olson timezone at the location of interest. |
NOAA used the reference below to develop their Sunrise/Sunset
https://gml.noaa.gov/grad/solcalc/sunrise.html and Solar Position
https://gml.noaa.gov/grad/solcalc/azel.html Calculators. The algorithms include corrections for atmospheric refraction effects.
Input can consist of one location and at least one POSIXct times, or one POSIXct time and at least one location. solarDep is recycled as needed.
Do not use the daylight savings time zone string for supplying dateTime, as many OS will not be able to properly set it to standard time when needed.
The localStdTime_UTC
column in the returned dataframe is primarily for
internal use and provides an important tool for creating LST daily averages
and LST axis labeling.
A dataframe with times and masks.
Internal functions used for ephemerides calculations were copied verbatim from the now deprecated maptools package source code in an effort to reduce the number of package dependencies.
Compared to NOAA's original Javascript code, the sunrise and sunset estimates from this translation may differ by +/- 1 minute, based on tests using selected locations spanning the globe. This translation does not include calculation of prior or next sunrises/sunsets for locations above the Arctic Circle or below the Antarctic Circle.
US EPA regulations mandate that daily averages be calculated based on "Local Standard Time" (LST) (i.e. never shifting to daylight savings). To ease work in a regulatory context, LST times are included in the returned dataframe.
Meeus, J. (1991) Astronomical Algorithms. Willmann-Bell, Inc.
NOAA notes that “for latitudes greater than 72 degrees N and S, calculations are accurate to within 10 minutes. For latitudes less than +/- 72 degrees accuracy is approximately one minute.”
Sebastian P. Luque [email protected], translated from Greg Pelletier's [email protected] VBA code (available from https://ecology.wa.gov/Research-Data/Data-resources/Models-spreadsheets/Modeling-the-environment/Models-tools-for-TMDLs), who in turn translated it from original Javascript code by NOAA (see Details). Roger Bivand [email protected] adapted the code to work with sp classes. Jonathan Callahan [email protected] adapted the source code from the maptools package to work with MazmaTimeSeries classes.
library(MazamaTimeSeries) Carmel <- Carmel_Valley %>% mts_filterDate(20160801, 20160810) # Create timeInfo object for this monitor ti <- timeInfo( Carmel$data$datetime, Carmel$meta$longitude, Carmel$meta$latitude, Carmel$meta$timezone ) t(ti[6:9,]) # Subset the data based on day/night masks data_day <- Carmel$data[ti$day,] data_night <- Carmel$data[ti$night,] # Build two monitor objects Carmel_day <- list(meta = Carmel$meta, data = data_day) Carmel_night <- list(meta = Carmel$meta, data = data_night) # Plot them plot(Carmel_day$data, pch = 8, col = 'goldenrod') points(Carmel_night$data, pch = 16, col = 'darkblue')
library(MazamaTimeSeries) Carmel <- Carmel_Valley %>% mts_filterDate(20160801, 20160810) # Create timeInfo object for this monitor ti <- timeInfo( Carmel$data$datetime, Carmel$meta$longitude, Carmel$meta$latitude, Carmel$meta$timezone ) t(ti[6:9,]) # Subset the data based on day/night masks data_day <- Carmel$data[ti$day,] data_night <- Carmel$data[ti$night,] # Build two monitor objects Carmel_day <- list(meta = Carmel$meta, data = data_day) Carmel_night <- list(meta = Carmel$meta, data = data_night) # Plot them plot(Carmel_day$data, pch = 8, col = 'goldenrod') points(Carmel_night$data, pch = 16, col = 'darkblue')