R Spatial Analysis using SP
description
Transcript of R Spatial Analysis using SP
Applied Spatial Data Analysis using R
Thomas JaggerDepartment of Geography
Florida State University
Denver R User Group MeetingOctober 19, 2010
with special thanks to
Roger Bivand: http://www.asdar-book.org
TopicsTopics
1. Spatial objects in the “sp” Package• Points, Lines, Polygons, Pixels and Grids
2. The S4 Framework • Classes, slots, methods, inheritance
3. How to create, convert, explore and manipulate “sp” spatial objects.
4. Example: Analyzing tornado data using the R “sp” package.
Sources of Information
Spatial data:1.http://cran.r-project.org/web/views/Spatial.html2.http://r-spatial.sourceforge.net/ 3.vignette("sp")4.Rnews: http://cran.r-project.org/doc/Rnews/Rnews_2005-2.pdf5.Applied Spatial Data Analysis with R6.http://spatial-analyst.net wiki
Plotting 1.http://r-spatial.sourceforge.net/gallery/2.Figures for ASDAR Tornado data from the Storm Prediction Center (SPC)Slides on Spatial Data Courtesy of Roger Bivand http://spatial-analyst.net/Rosgeo/sites/default/files/plasencia_monday_R.pdf
Object Framework
•To begin with, all contributed packages for handling spatial data in R had different representations of the data. •This made it difficult to exchange data both within R between packages, and between R and external file formats and applications.•The result has been an attempt to develop shared classes to represent spatial data in R, allowing some shared methods and many-to-one, one-to-many conversions.•Roger Bivand and his collaborators chose to use new-style classes to represent spatial data and they are confident that this choice was justified.
Spatial Points• The most basic spatial data object is a point, which may have
2 or 3 dimensions
• Consists of a single coordinate, or a set of such coordinates.
• To define a SpatialPoints object; coordinates should be of mode double and will be promoted if not already.
• The points in a SpatialPoints object may be associated with a row of attributes to create a SpatialPointsDataFrame object
• The coordinates and attributes may, but do not have to be keyed to each other using ID value.
• Objects can be manipulated as a data frame though they appear as GIS objects i.e. features with attributes.
• Spatial objects rarely created from scratch, rather they are created by promoting another object such as a data frame into a SpatialPointsDataFrame object.
Spatial Points Diagram
• The boxes are the object classes definition– Blue is the class name– White represents slots within each class– Arrows show inheritance
Spatial Points Example:Colorado Tornado Touchdowns
require(sp)download.file("http://www.spc.noaa.gov/gis/svrgis/
Tornado_touchdown_points.zip","Tornado_touchdown_points.zip",mode="wb")
require(maptools)Tornado<-
read.dbf(zip.file.extract("Tornado_touchdown_points.dbf",zip="Tornado_touchdown_points.zip"))
TornadoContUS<-subset(Tornado, !(FIPS %in% c(2,66,15,60,72,78,99)) & SLAT !=0 & SG ==1 & FSCALE >=0)
ColTornado<-subset(TornadoContUS,STATE=="CO")
coordinates(ColTornado)<-c("SLON","SLAT")
class(ColTornado) #"SpatialPointsDataFrame“
str(ColTornado)Formal class 'SpatialPointsDataFrame' [package "sp"] with
5 slots
..@ data :'data.frame': 1762 obs. of 25 variables:
..@ coords.nrs : int [1:2] 16 15 ;data columns
..@ coords : num [1:1762, 1:2] -103 -102 -102 -102 -104 ... ;coordinates longitude, lattitude
.. ..- attr(*, "dimnames")=List of 2 ;column names
..@ bbox : num [1:2, 1:2] -109 37 -102 41
.. ..- attr(*, "dimnames")=List of 2
..@ proj4string:Formal class 'CRS' [package "sp"] with 1 slots ;projection string (we will assign one later)
Spatial Lines and Polygons• Line object is a collection of 2D coordinates (contours).
• Polygon object: Line object with equal first and last coordinates.
• Lines object: list of Line objects (10,000 foot contour lines)
• Polygons object: list of Polygon objects (country with islands)
• SpatialLines or SpatialPolygons objects are made from lists of Lines or Polygons objects (respectively).
• SpatialLinesDataFrame and SpatialPolygonsDataFrame objects – Extends SpatialLines and SpatialPolygons classes,– Contain objects and standard data frames,– require ID field values to match data frame row names.
• Multiple page dotted object denotes list of objects• Bold arrow shows a slot containing a list of objects• Plain arrow shows a slot containing a single object
Spatial Polygons Classes and Slots Diagram
Plotting Spatial Objects Example
Procedure:
1. Create a FACTOR of F values (for plotting).
2. Load Colorado counties map.
3. Convert map to SpatialLines object.
4. Create grid lines and grid text.
5. Us spplot to create plot (and print to display).
Plot Colorado touchdown points colored by Fujita scale on top of a map of Colorado counties with a labeled grid of latitude and longitude lines.
range(ColTornado$FSCALE) #0:3
ColTornado$FSCALE_FACTOR<-ordered(ColTornado$FSCALE,levels=0:5, labels=paste("F",0:5,sep=""))
require(maps) #Load in maps package:
ColMap<-map("county","Colorado",plot=F)
baseCRS<-CRS("+proj=longlat +ellps=WGS84")
#Convert it to a SpatialLines object. You can convert to SpatialPolygons as well. Projection added
ColMapSpLines<- map2SpatialLines(ColMap,proj4string=baseCRS)
ColMapSpLinesLayout<- list("sp.lines",ColMapSpLines,lwd=.6,col="grey50")
#Create grid lines and grid text along with plot layouts
latlonlines<-gridlines(ColMapSpLines,easts= -110:-101 )
latlonlinesLayout<-list("sp.lines",latlonlines,lty=2,col="pink")
latlontext<-gridat(latlonlines)
#Split for better use of positioning
latlontextE<-latlontext[latlontext$pos==1,]
latlontextN<-latlontext[latlontext$pos==2,]
latlontextLayoutE<-list("sp.text",coordinates(latlontextE), parse(text=as.character(latlontextE$labels)),offset=latlontextE$offset[1]/2,pos=1,col="brown")
latlontextLayoutN<-list("sp.text",coordinates(latlontextN), parse(text=as.character(latlontextN$labels)),offset=latlontextN$offset[1]/2,pos=2,col="green")
spLayout<-list(ColMapSpLinesLayout, latlonlinesLayout, latlontextLayoutE, latlontextLayoutN)
spplot(ColTornado["FSCALE_FACTOR"],
pch=20, alpha=.8, key.space="right”,
xlim=c(-109.8,101.5), ylim=c(36.5,41.5), col.regions=c("grey","yellow","orange","red","brown", "black"), main="Colorado Tornadoes from 1950 to 2009", sp.layout=spLayout)
The spplot function
1. plots one color for each FSCAL_FACTOR level.
2. uses trellis graphics from lattice package.
3. adds layers in sp.layout in order.
4. uses alpha for transparency. (density plot)
Counting Storms ExampleThe goal of this example is to count storms in
hexagons of uniform area covering the United States from 1980-2009.
The example demonstrates how to:
1.Convert spatial objects from one CRS to another.
2.Generate a hexagonal lattice as a Spatial Polygon.
3.Use of overlay() to count touchdown points within each polygon.
4.Use spplot() to plot the analysis.
Counting Storms Procedure1. Select 1980-2009 subset of tornado touchdowns.
2. Create a Lambert CRS and project “SLAT”,”SLON” coordinates onto new CRS.
3. Create SpatialPointsDataFrame of touchdowns.
4. Create equal area SpatialPolygons hexagon tiling.
5. Overlay spatial points onto hexagon tiling.1. Use overlay() to return an integer vector identifying the
location of the polygon containing each point.
6. Count touchdown points within each hexagon.
7. Import US map and convert to Lambert CRS.
8. Create gridlines and project onto Lambert CRS.
9. Plot counts on US map with gridlines using spplot.
require(rgdal) #rgdal code in green
projInfo()[55,] #lcc Lambert Conformal Conic
lambertCRS<-
" +proj=lcc +lat_1=60 +lat_2=30 +lon_0=-100"
#Spacing (and lack of) intentional in CRS string.
#project() uses matrix with longitude latitude cols.
#CRS string cannot contain reference ellipsoid.
res=project(cbind(Tornado2$SLON,Tornado2$SLAT), lambertCRS)
Tornado2$x=res[,1]; Tornado2$y=res[,2]
#Make copy, convert to SpatialPointsDataFrame
US_sp=Tornado2
coordinates(US_sp)=~x+y
#Create polygon
coords1<-matrix(c(-125,20, -125,50, -66,50 ,-66,20,-125,20),
ncol=2, byrow=TRUE)
coords=project(coords1,lambertCRS)
pg=Polygon(coords) #rectangle in Lambert CRS
#Sample hexagonal points, convert to polygons
HexPts=spsample(pg, type="hexagonal", n=2750, offset=c(0,0))
HexPols = HexPoints2SpatialPolygons(HexPts)
proj4string(HexPols)<-lambertCRS #" +proj=lcc +lat_1=60 +lat_2=30 +lon_0=-100 +ellps=WGS84“
#transform back into lon, lat coordinates and plot
HexPolsLatLon<-spTransform(HexPols,baseCRS)
plot(HexPolsLatLon,axes=T) #hexagon tiling
#overlay locations, returns hexagon locationlocations=overlay(US_sp,HexPols)#Use of table function to count points in hexagoncounttable<-as.data.frame(
table(factor(locations, levels=1:length(HexPols@polygons))),
row.names=
sapply(HexPols@polygons, function(x) x@ID)
)[,"Freq",drop=F]
colnames(counttable)<-"counts“
HexPolsDf = SpatialPolygonsDataFrame( HexPols, counttable, match.ID = TRUE)
#Create state and gridline map elements
CRSlambert<-CRS(lambertCRS)
usa_lines=map("state",plot=F)
usa_lines_sp=map2SpatialLines( usa_lines,proj4string=baseCRS) #in maptools
usa_lines_sp_trans=spTransform( usa_lines_sp, CRSlambert)
#Create SpatialPolygons object and create grid
frame<-SpatialPolygons(
list(Polygons(list(Polygon(coords1)), "ID1")),
proj4string=baseCRS)t1<-gridlines(frame, norths=seq(25,50,5), easts=seq(-120,-60,15))
grid_lines<-spTransform(t1,CRSlambert)
#Create mappings and plot
L1=list("sp.lines",usa_lines_sp_trans,lwd=.6)G1=list("sp.lines",grid_lines,col="grey50")
#spplot produces object, plotted by print()!spplot(HexPolsDf,lty=0,
col.regions=rev(heat.colors(100)), sp.layout=list(l1,G1), colorkey=list(space="bottom"))
Monthly Tornado Counts and Global Climate Covariates
Is there any relationship between climate covariates and monthly tornado counts for a given hexagon.
• Covariates: monthly NAO, SST, SSN, and SOI?• Our initial investigation will divide monthly
tornado counts by the lower and upper terciles (thirds) of the same month for each covariate. – This generates 2*4*12 observations to be plotted two
at a time. 48 plots each with 2 subplots.
• The 48 plots are combined into a movie using QuickTime Pro, and converted to SWF using Fs
Monthly Covariate Procedure• Download covariates and unstack by month and year.
• Generate monthly quantiles (terciles) for the covariates.
• Merge covariates with climate data.
• Create SpatialPointsDataFrame (SPDF) from merged dataset.
• Overlay SPDF onto hexagon SpatialPolygons tiling.
• Add hexagon id as “hex” column to SPDF.
• Split SPDF by Hexagon id and remove empty hexagons from hexagon tiling (i.e. id not in SPDF@data[“hex”])
• For each covariate and each month, table the tornado touchdown points in the given month by the terciles of the given covariate observed in that month.
• Create SpatialPolygonsDataFrame from result.
• Plot each figure as PNG and combine into movie.
#Download Covariates and create Quantiles
#Climate Covariates from 1861-2009
source("data/climateCovariates.R")
# Green colored functions from:
source("funs/tsupport.R")
startend<-1950:2009 #tornado years
covariates<-make.cov.unstacked(climateCovariates, se=startend,cov=c("soi","nao","sst","sun"))
monthlyquantiles<-as.array.list(lapply(
split(covariates[,-(1:2)], covariates$Month),
function(x) out<- apply(x,2,quantile,probs=c(1/4,1/3,1/2,2/3,3/4) )
),name="Month")
TornadoClimate<-merge(TornadoContUS, covariates, by.x=c("YEAR","MONTH"), by.y=c("Year","Month"))
projcords=project( as.matrix(TornadoClimate[c("SLON","SLAT")]), lambertCRS) #As before
TC<-TornadoClimate
TC$x<-projcords[,1];TC$y<-projcords[,2]
coordinates(TC)=~x+y
hexagonNumber<-overlay(TC,HexPols)
TC$Hex<-hexagonNumber
#Split Hexagons (Will order by hex number)
TCsplit<-split(TC@data,TC$Hex)
names(TCsplit)<-sapply(HexPols@polygons, function(x) x@ID)[as.numeric(names(TCsplit))]
#Remove empty tiles from hexagon tiling. (V10.1 R)
HexPolsMissing<-HexPols[names(TCsplit),]
#Create Yearly Frequency
yearspersplit<-count.storms(x=covariates,cut=3,col.name="Month", quantiles = monthlyquantiles,Year%in%startend)
splitcounts<-data.frame(t(sapply(TCsplit, function(x) count.storms(x,cut=3, FSCALE>=1 & YEAR %in% startend, quantiles = monthlyquantiles) ) /yearspersplit) )
#Create SpatialPolygonsDataFrame
splitcountsSPDF<-SpatialPolygonsDataFrame(HexPolsMissing,splitcounts)
#Create Images
dir.create("./monthlyclimatepng")
png(file="./monthlyclimatepng/plot%03d.png", width=1080, height=600, bg="white",res=120)
for(i in 1:48) #4 covariates 12 months
{
#Plot lower and upper thirds in each plot
print(spplot(splitcountsSPDF[,c(3*i-2,3*i)], lty=0, col.regions=rev(heat.colors(100))[1:90], sp.layout=list(l1,G1), as.table=T,
main="Tornado frequency of F1 or higher split by covariate", colorkey=list(space="bottom")))
}
dev.off()
Final Thoughts1. This is an introduction to the “sp” package
as it relates to our initial work using a tornado data set.
2. We did not get to discuss• GridTopology a base class for• SpatialGrid a rectangular array class and• SpatialPixels a sparse array class
3. Source code and presentation available:• spexample.zip and sp.ppt from
https://public.me.com/thjagger• Examples tested on R V10.1 on 32 bit Vista
– Unzip into dir, start R in dir\spexample– source(“tornado.r”,echo=T) #Creates all figures, x11()