Chapter 13

Spatiotemporal Point Observations

13.1 Introduction

Throughout this chapter we will revisit the data from the Integrated Air Quality system of the Madrid City Council (section 10.1) to illustrate visualization methods applicable for point space-time data. This dataset comprises the time series of measurements acquired at each station of the network during 2011. In the section 8.1 the data were converted from spatiotemporal data to spatial data, where the time information was suppressed to display only the yearly average values. In this chapter we will work with the whole space-time dataset using the tools provided by the spacetime package (E. Pebesma 2012).

13.2 Data and Spatial Information

The starting point is to retrieve the data and combine it with the spatial and temporal information. The data are contained in the airQuality data.frame, and the locations are in airStations, a data.frame that is converted to a SpatialPointsDataFrame object with the coordinates method.

library(sp)

## Spatial location of stations
airStations <- read.csv2(’data/airStations.csv’)
## rownames are used as the ID of the Spatial object
rownames(airStations) <- substring(airStations$Codigo, 7)
coordinates(airStations) <- ~ long + lat
proj4string(airStations) <- CRS(“+proj=longlat+ellps=WGS84”)
## Measurements data
airQuality <- read.csv2(’data/airQuality.csv’)
## Only interested in NO2
NO2 <- airQuality[airQuality$codParam==8,]

Each row of this data.frame corresponds to a measurement at one of the stations during a day of the year (long format, following the schema proposed in (E. Pebesma 2012)).

The spacetime package defines several classes for spatiotemporal data inheriting the classes defined by the sp and xts packages. In particular, the STFDF, a class for spatiotemporal data with full space-time grids with n spatial locations and m times, requires a data.frame with n·m rows, (spatial index moving fastest). Thus, we need to transform this structure to build a multivariate time series where each station is a different variable (space-wide under the schema of (E. Pebesma 2012)). The procedure is

  • Add a column with the POSIXct time index.
  • Reshape the data.frame from long to wide format with reshape.
  • Define a multivariate time series with zoo (Figure 13.3).
  • Coerce this time series to a vector with n·m rows.
library(zoo)
library(spacetime)

NO2$time <- with(NO2, ISOdate(year, month, day))
NO2wide <- reshape(NO2[,c(’codEst’, ’dat’, ’time’)],
   idvar=’time’, timevar=’codEst’,
   direction=’wide’)
NO2zoo <- zoo(NO2wide[,-1], NO2wide$time)

dats <- data.frame(vals=as.vector(t(NO2zoo)))
NO2st <- STFDF(airStations, index(NO2zoo), dats)

13.3 Graphics with spacetime

The stplot function of the spacetime package supplies the main visualization methods for spatiotemporal data. When the mode xy is chosen (default) it is mainly a wrapper around spplot and displays a panel with the spatial data for each element of the time index (Figure 13.1). The problem with this approach is that only a limited number of panels can be correctly displayed on one page. In this example, we print the first 12 days of the sequence.

Figure 13.1

Figure showing scatterplots of the no2 values (2011) with a panel for each day of the time series. each circle represents a different station.

Scatterplots of the NO2 values (2011) with a panel for each day of the time series. Each circle represents a different station.

airPal <- colorRampPalette(c(’springgreen1’, ’sienna3’, ’gray5’))(5)

stplot(NO2st[, 1:12], cuts=5, col.regions=airPal, edge.col=’black’)

With the mode xt, a space-time plot with space on the x-axis and time on the y-axis is plotted (Figure 13.2).

Figure 13.2

Figure showing space-time graphic of the no_2 time series. each column represents a different station (denoted with the last two digits of the code).

Space-time graphic of the NO_2 time series. Each column represents a different station (denoted with the last two digits of the code).

stplot(NO2st, mode=’xt’, col.regions=colorRampPalette(airPal)(15),
  scales=list(x=list(rot=45)), ylab=’’, xlab=’’)

Finally, with the mode ts, data are coerced to a multivariate time series that is displayed in a single plot (Figure 13.3).

Figure 13.3

Figure showing time graph of the no2 time series (2011). each line represents a different station.

Time graph of the NO2 time series (2011). Each line represents a different station.

stplot(NO2st, mode=’ts’, xlab=’’,
 lwd=0.1, col=’black’, alpha=0.6,
 auto.key=FALSE)

These three graphics complement each other and together provide a more complete view of the behavior of the data. For example in Figure 13.1, we can find stations whose levels remain almost constant throughout the 12-day period (namely, El Pardo-280790581, the station at the top-left corner that is far from the city center), while others fluctuate notably during this same period (for example, Barajas-28079027 and Urb. Embajada-28079055, the two nearby stations at the right). On the other hand, Figure 13.2 loses the spatial information but gives a more comprehensive view of the evolution of the network. The station El Pardo-28079058 is significantly below the rest of the stations during the whole year, with the station Pza. Fdez Ladreda-28079056 being the opposite. In between, the stations could be divided into two or three groups according to their levels. Regardless, the group of stations reaches maximum values during the first days of autumn and at the end of winter. These maxima are clearly displayed in Figure 13.3.

13.4 imageAnimation

Another approach for displaying this spatiotemporal data is using animation. Once again, we will take advantage of the functionalities of the gridSVG package.

13.4.1 Initial Snapshot

The first step is to define the initial parameters of the animation: starting values and duration.

library(gridSVG)
## Initial parameters
start <- NO2st[,1]
## values will be encoded as size of circles,
## so we need to scale them
startVals <- start$vals/5000

nStations <- nrow(airStations)
days <- index(NO2zoo)
nDays <- length(days)
## Duration in seconds of the animation
duration <- nDays*.3

The first snapshot of the data is produced with spplot. We define an auxiliary function, panel.circlesplot, to display the data encoding values with circles of variable size and color. This function uses grid.circle from the grid package.

The subsequent frames of the animation will modify the colors and sizes of the circles according to the NO2st object.

library(grid)

## Auxiliary panel function to display circles
panel.circlesplot <- function(x, y, cex, col=’gray’,
     name=’stationsCircles’, ...){
grid.circle(x, y, r=cex,
  gp=gpar(fill=col, alpha=0.5),
  default.units=’native’, name=name)
}
pStart <- spplot(start, panel=panel.circlesplot,
   cex=startVals,
   scales=list(draw=TRUE), auto.key=FALSE)
pStart

13.4.2 Intermediate States to Create the Animation

From this initial state, grid.animate creates a collection of animated graphical objects with the intermediate states defined by animUnit and animValue. As previously stated, the NO2 values will be encoded with the radius of each circle, and the color of the circles will distinguish between weekdays and weekend. The use of rep=TRUE ensures that the animation will be repeated indefinitely.

## Color to distinguish between weekdays (’green’)
## and weekend (’blue’)
isWeekend <- function(x) {format(x, ’%w’) %in% c(0, 6)}
color <- ifelse(isWeekend(days), ’blue’, ’green’)
colorAnim <- animValue(rep(color, each=nStations),
     id=rep(seq_len(nStations), nDays))

## Intermediate sizes of the circles
vals <- NO2st$vals/5000
vals[is.na(vals)] <- 0
radius <- animUnit(unit(vals, ’native’),
     id=rep(seq_len(nStations), nDays))

## Animation of circles including sizes and colors
grid.animate(’stationsCircles’,
  duration=duration,
  r=radius,
  fill=colorAnim,
  rep=TRUE)

13.4.3 Time Reference: Progress Bar

Information from an animation is better understood if a time reference is included, for example with a progress bar. The following code builds a progress bar with ticks at the first day of each month, and with color changing from gray (background) to blue as the time advances. On the other hand, it is convenient to provide a method so the user can stop and restart the animation sequence if desired. This functionality is added with the definition of two events, onmouseover and onmouseout, included with the grid.garnish function.

## Progress bar
prettyDays <- pretty(days, 12)
## Width of the progress bar
pbWidth <- .95
## Background
grid.rect(.5, 0.01, width=pbWidth, height=.01,
   just=c(’center’, ’bottom’),
   name=’bgbar’, gp=gpar(fill=’gray’))

## Width of the progress bar for each day
dayWidth <- pbWidth/nDays
ticks <- c(0, cumsum(as.numeric(diff(prettyDays)))*dayWidth) + .025
grid.segments(ticks, .01, ticks, .02)
grid.text(format(prettyDays, ’%d-%b’),
    ticks, .03, gp=gpar(cex=.5))
## Initial display of the progress bar
grid.rect(.025, .01, width=0,
   height=.01, just=c(’left’, ’bottom’),
   name=’pbar’, gp=gpar(fill=’blue’, alpha=’.3’))
## ...and its animation
grid.animate(’pbar’, duration=duration,
  width=seq(0, pbWidth, length=duration),
  rep=TRUE)
## Pause animations when mouse is over the progress bar
grid.garnish(’bgbar’,
   onmouseover=’document.rootElement.pauseAnimations()’,
   onmouseout=’document.rootElement.unpauseAnimations()’)

The SVG file is finally produced with gridToSVG (Figure 13.4)

Figure 13.4

Figure showing animated circles of the no2 space-time data with a progress bar.

Animated circles of the NO2 space-time data with a progress bar.

grid.export(’figs/NO2pb.svg’)

13.4.4 Time Reference: A Time Series Plot

A different and more informative solution is to add a time series plot instead of a progress bar. This time series plot displays the average value of the set of stations, with a point and a vertical line to highlight the time position as the animation advances (Figure 13.5).

Figure 13.5

Figure showing animated circles of the no2 space-time data with a a time series as reference.

Animated circles of the NO2 space-time data with a a time series as reference.

## Time series with average value of the set of stations
NO2mean <- zoo(rowMeans(NO2zoo, na.rm=TRUE), index(NO2zoo))
## Time series plot with position highlighted
pTimeSeries <- xyplot(NO2mean, xlab=’’, identifier=’timePlot’) +
  layer({
  grid.points(0, .5, size=unit(.5, ’char’),
    default.units=’npc’,
    gp=gpar(fill=’gray’),
    name=’locator’)
  grid.segments(0, 0, 0, 1, name=’vLine’)
 })

print(pStart, position=c(0, .2, 1, 1), more=TRUE)
print(pTimeSeries, position=c(.1, 0, .9, .25))

Once again, grid.animate creates a sequence of intermediate states for each object of the graphical scenes: The signaling point and vertical line follow the time evolution, while the sizes and colors of each station circle change as in the previous approach. Moreover, the onmouseover and onmouseout events are defined with grid.garnish so the user can pause and restart the animation by hovering the mouse over the time series plot.

grid.animate(’locator’,
  x=unit(as.numeric(index(NO2zoo)), ’native’),
  y=unit(as.numeric(NO2mean), ’native’),
  duration=duration, rep=TRUE)

xLine <- unit(index(NO2zoo), ’native’)

grid.animate(’vLine’,
  x0=xLine, x1=xLine,
  duration=duration, rep=TRUE)

grid.animate(’stationsCircles’,
  duration=duration,
  r=radius,
  fill=colorAnim,
  rep=TRUE)

## Pause animations when mouse is over the time series plot
grid.garnish(’timePlot’, grep=TRUE,
  onmouseover=’document.rootElement.pauseAnimations()’,
  onmouseout=’document.rootElement.unpauseAnimations()’)

grid.export(’figs/vLine.svg’)

1 Use Figure 8.5 as reference of the positions and codes of the stations.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.227.102.159