R:pems.utils Plotting

Karl Ropkins

2024-12-23

Background

The R package pems.utils uses two main data types: pems.elements, data-series with assigned units, and pems, datasets of simultaneously logged pems.elements.

This document provides an overview of their plotting in R.

For a quick and more general introduction to pems.utils, see [>pems.utils introduction] or to return to the [>website index].

If you have any suggestions how to make either pems.utils or this document better or you have any problems using either, please let me know [>email me].

Unless you have setup R to automatically load pems.utils, you will need to load it e.g. using library(pems.utils) to use the functions described here.

pems.utils includes a number of specialist graphics functions developed specifically for use with pems and pems.element data types. However, pems.utils is primarily a data handling and analysis package, and outputs have been designed to allow users the flexibility to work with other graphics packages.

Generic Plots:

The pems.utils package includes generic plotting methods for both pems and pems.elements data types.

So, both data types can be handled using standard plot(…) calls, e.g.:

plot(pems.1)
plot(pems.1$local.time, pems.1$conc.co)

Here, plot(pems, …) behaves like a plot(data.frame, …) and generates a co-plot, and plot(pems.element, …) behaves like plot(vector, …) and generates a conventional scatterplot.

These generic plots accept most common plot arguments, e.g. type, col and lty, making this is simple-to-use option for most R users.

For more about other generic functions like plot in pems.utils, see [>pems.utils generics].

Working with other Graphics Packages

Although there are some important differences, discussed in the package introduction, pems behave in a similar fashion to other (row and column) data set objects like data.frames and data.tables, and pems.elements behave in a similar fashion to other vector objects like numerics, characters and factors when used with other packages.

So, generally, anything you can do in a graphic package with a data.frame or a vector you should be able to do with a pems or a pems.element, respectively.

For example, pems data sets can be treated like conventional data.frames in either lattice or ggplot2 plots:

require(lattice)
xyplot(conc.co~local.time, data=pems.1)
require(ggplot2)
ggplot(pems.1) + geom_point(aes(x=local.time, y=conc.co))

If you are plotting pems.utils outputs with these or other packages and have any suggestions how to make either plot handling or this document better or you have any problems, please let me know. [>email me].

pemsPlot

pemsPlot is the main workhorse function for plotting pems.utils outputs.

It accepts x and y arguments like plot, which can be supplied directly or sourced from a data set supplied as data in the same call.

Plot outputs can be easily modified using additional arguments and functions, e.g.:

#plot 1:default x/y plot
pemsPlot(local.time, velocity, data=pems.1)

#add a  'referencing' term for grouping, etc... 
pems.1$ref <- refRow(pems.1, breaks=c(405,660))

#plot 2: grouped line plot with y axis reset to miles per hour
pemsPlot(local.time, velocity, data=pems.1, group=ref,
         type="l", grid.lty=3, y.to="mph")

#plot 3: conditioned type h plot with full dataset ghosts plotted 
#(type h is a drop line plot;  h comes from histogram-like)
p <- pemsPlot(local.time, velocity, data=pems.1, 
         cond=ref, type="h")
loa::add.XYZGhosts(p)

pemsPlots accepts (optional) arguments: z which is by default linked to point size and color; groups for within-plot grouping and cond for multiple plot panelling.

Like plot, it accepts common plotting arguments, e.g. type to change between point and line outputs, but it also accepts loa style commands, e.g. grid.lty to change the line style of grid lines without affecting other lines in the plots, and commands like y.to that access pems information to change plot element scales and units.

Other functions can also be used to add addition elements to existing plots, e.g. here add.XYZGhosts from loa is used to add a ‘ghost’ versions of the full dataset to all panels in a multiple panel plot.

pemsPlot is highly flexible, and used with other panel… and loa add… functions, can be easily used to generate many plots commonly used in PEMS data analysis with just a few lines of code.

For example, data maps from plots of GPS latitude and longitude data:

#map 1: CO2 Emissions bubble plot, first 300 measurements 
pems.1$em.co2 <- calcEm(conc.co2, data=pems.1)
p <- pemsPlot(longitude, latitude, em.co2,
              data=pems.1[1:300,], grid=FALSE,
              col.regions=c("red", "black"))
loa::add.LonLatMap(p, map.type="osm")

#map 2: vehicle journey path, first 300 measurements
p <- pemsPlot(longitude, latitude, 
              data=pems.1[1:300,], grid=FALSE,
              panel=panel.routePath)
loa::add.LonLatMap(p, map.type="bing", 
              recolor.map=c("darkgrey", "white", "white", "white"))

Both examples limit the plot range to the first 300 rows of the pems.1 dataset.

In map 1 the supplied emission measurement, em.co2, is used as the z pemsPlot argument to generate a bubble plot. Other plot arguments are also used to modify the plot appearance, e.g. col.regions to change the palette coloring points, and then add.LonLatMap from loa is used to add a same-location map, in this case an open street map tile.

In map 2, a route-path panel is used to plot the vehicle journey this time on a satellite image from bing which was recolored before plotting.

The map layers were generated using code in loaMapPlot in loa, and the map layers are (c) OpenStreetMap contributors.

Plots can be easily extended to include multiple time-series and axes, e.g.:

#calculate emissions for pems.1 CO, NOx and HCs:
pems.1$em.co <- calcEm(conc.co, data=pems.1)
pems.1$em.nox <- calcEm(conc.nox, data=pems.1)
pems.1$em.hc <- calcEm(conc.hc, data=pems.1)

#multi-species time-series of exhaust emissions 
#superimposed on the emitting vehicle's speed profile  
p <- pemsPlot(local.time, cpe(em.co, em.nox*5, em.hc*10),
         data=pems.1, type="l", ylab="", 
         col=c("red", "blue", "darkgreen"), 
         key.groups.main="Emissions\n[g/sec]", 
         key.position="left")
p <- loa::add.Y2Axis(p, ylab="speed", col="grey", rescale=200)
loa::add.XYPolygon(p, x=local.time, y=velocity,
              data=pems.1, col="grey", 
              y2.scale=TRUE, first=TRUE)

Here, the cpe function is used to group multiple y axis data-series and scale them manually, and other arguments are used to control plot appearance and layout, e.g. col to color y time-series directly and key… arguments are used to position and label the key.

Then add… functions are used to add a second y-axis, and a polygon layer, plotted on that second axis scale, showing the vehicle speed profile.

Other Packaged Plots

Other plots included in the pems.utils package are meant for use with specific pems.elements.

WatsonPlot

Supplied speed and acceleration time-series, the WatsonPlot generates variations on Watson’s classic speed/accel frequency distribution plot1, e.g.:

#calculate acceleration and CO2 emissions
pems.1$accel <- calcAccel(velocity, local.time, 
                          data = pems.1)
pems.1$em.co2 <- calcEm(conc.co2, data = pems.1)

#plot 1: speed/accel frequency distribution as bin plot 
WatsonPlot(velocity, accel, data=pems.1, omit.stopped="cells")

#plot 2: speed/accel/emissions distribution as fitted surface 
WatsonPlot(velocity, accel, em.co2, data=pems.1, plot.type=4,
           omit.stopped="points", too.far=0.05,
           col.regions=c("yellow", "purple"))

The WatsonPlot generates frequency distributions when supplied x and y time-series, and z-statistic distributions when supplied x, y and z time-series.

Idling and/or stopped vehicle data can often dominate PEMS activity data, so the function includes an extra argument, omit.stopped, which provides options for handling related data. Options are points, which removes stopped-vehicle data before binning the data, and cells, which removes any cells containing stopped-vehicle data after binning it.

The WatsonPlot includes several plot types. The examples shown here are a bin plot, which is the default plot output, and plot.type = 4, which is a fitted surface (used in second plot above). By default, surface fits are extrapolated across the full data range, but the extra argument too.far can be used to limit the amount of extrapolation.)

The coldStartPlot:

Supplied local time and emissions time-series, the coldStartPlot generates cold start emissions plots, e.g.:

#calculate CO emissions 
pems.1$em.co <- calcEm(conc.co, data = pems.1)

#plot 1: cold start accumulative emissions
coldStartPlot(local.time, em.co, data=pems.1, engine.on=30)

#plot 2: cold start emission profile 
coldStartPlot(local.time, em.co, data=pems.1, engine.on=30,
              plot.type=2)

By default the coldStartPlot generates a conventional accumulated emissions profile2, fits a cold start model to that data, and reports the estimated cold start contribution and cold start operating time.

Because PEMS systems are often started before the monitored vehicle engine, the extra argument engine.on can be used to exclude an pre-engine-on data from model inputs and calculations.

The cold start end point is automatically assigned using a related pems.utils function fitColdStart3. The function currently includes two variations on the automatic cold start assignment model: a single break-point fit to the accumulated emissions profile (model 1) and a modification of that (model 2). Model 2 is the current default.

The default accumulated emisssion profile coldStartPlot is widely used when reporting cold start emissions. One other option, an emission profile cold start contribution plot, is also included as plot.type 2.

VSPPlot and VSPBinPlot

Supplied vehicle specific power (VSP) and emissions time-series, the VSPPlot generates a VSP/emission plot, and supplied binned VSP data, the VSPBinPlot generates binned VSP profiles, e.g.:

#calculate VSP, VSPBins and CO2 emissions 
pems.1 <- pems.utils::pems.1
pems.1$vsp <- calcVSP(velocity, time = local.time, data = pems.1)
pems.1$vspbin <- refVSPBin(vsp, data=pems.1)
pems.1$em.co2 <- calcEm(conc.co2, data = pems.1)

#align CO2 emissions with VSP
pems.1 <- cAlign(vsp~em.co2, pems.1, output="pems")

#plot 1: VSPPlot of CO2 emissions with break-point model fitted
VSPPlot(vsp, em.co2, data = pems.1, break.point = TRUE,
        break.point.col="red")

#plot 2: VSPBinPlot of CO2 emissions as boxplot 
VSPBinPlot(vspbin, em.co2, data=pems.1, plot.type=2)

By default, VSPPlot generates a scatter plot of the supplied VSP and emissions data, but LOESS curves or break-point lines can also be added using the extra arguments loess and break.point, and modified by extension as in earlier examples.

VSPBinPlot generates a range of summary statistics plots for binned VSP data. By default, it generates a bar plot of VSP bin counts if suppied just the binned VSP data or a bar plot of binned VSP data mean emissions measurements if supplied binned VSP and emissions time-series. The statistical calculated if two inputs are supplied can also been modified using the additional argument stat.

Both VSPPlot and VSPBinPlot (assuming it is given two inputs) can also be used to generate a box plot using an additional argument, plot.method = 2.

These specialist plots made use pems and pems.element properties, e.g.:

pems units handling, see [>pems.utils units]

pems generics, see [>pems.utils generics]

If you have any suggestions how to make either pems.utils or this document better or you have any problems using either, please let me know. [>email me].

Return to the [>website index] or [>introduction].


  1. Watson, H.C., 1995. Effects of a wide range of drive cycles on the emissions from vehicles of three levels of technology. SAE transactions, pp.190-203.↩︎

  2. Heeb, N., Forss, A.-M., Wilhelm, P. Comparison of methane, benzene and alkyl benzenes cold start emission data of EURO I and EURO II three-way catalyst passenger cars and light duty vehicles from time resolved exhaust gas analysis. Proceedings of the International Symposium on Transport and Air Pollution, Boulder Colorado USA, September 17-19, 2001.↩︎

  3. Based on methods described Ropkins, K, Li, H and Carslaw, DC Real-World Cold Start Emissions from Vehicles in the UK On-Road Vehicle Fleet. In: 20th CRC On-Road Vehicle Emission Workshop, 22 - 24 March 2010, San Diego, US↩︎