SpatialPoints and SpatialPointsDataframe

亡梦爱人 提交于 2019-12-03 03:52:34

问题


Working with the sp package in R. I wonder when I would use SpatialPoints and when SpatialPointsDataframe. It seems so me that there is not much difference?!

Is the only difference that in a SpatialPointsDataframe I can store more attributes?! If so, can I create a SpatialPointDataframe from an existing Dataframe (if coordinates are exisiting in this dataframe) without taking the detour of creating spatialPoints?


回答1:


Both SpatialPoints and SpatialPointsDataFrame objects are S4 objects. It is true that the main structural difference is that, in the latter, there is an extra slot containing the attributes data. However the practical differences more significant. Just to give a few examples (using the built-in meuse database from package sp, containing geocoded contaminant data from the floodplain of the river Meuse).

library(sp)
data(meuse)
class(meuse)        # a data.frame
# [1] "data.frame"
head(meuse[,1:5])   # first 5 columns
#        x      y cadmium copper lead
# 1 181072 333611    11.7     85  299
# 2 181025 333558     8.6     81  277
# 3 181165 333537     6.5     68  199
# 4 181298 333484     2.6     81  116
# 5 181307 333330     2.8     48  117
# 6 181390 333260     3.0     61  137

coordinates(meuse) <- 1:2     # convert to spDF object; use first 2 columns for lon/lat
class(meuse)                  # now a SpatialPointsDataFrame
# [1] "SpatialPointsDataFrame"
# attr(,"package")
# [1] "sp"

Even though meuse is a SpatialPointsDataFrame, we can still index it as if it was a simple data.frame. Notice how we refer to the lead column of the attributes table as if meuse was a df, and notice how indexing works as it does in a df.

meuse[meuse$lead>500,1:5]        # high lead
#         coordinates cadmium copper lead zinc elev
# 55 (179973, 332255)    12.0    117  654 1839 7.90
# 60 (180100, 332213)    10.9     90  541 1571 6.68
meuse[meuse$lead<40,1:5]         # low lead
#              coordinates cadmium copper lead zinc  elev
# 112 (180328, 331158)     0.4     20   39  113 9.717
# 161 (180201, 331160)     0.8     18   37  126 9.036

We can also use the plot method for SpatialPointsDataFrames to plot the data.

par(mfrow=c(1,2), mar=c(2,2,2,2))    # 1 X 2 grid of plots; remove margins
plot(meuse, pch=20, main="Full Dataset", axes=TRUE)
plot(meuse, 
     bg=rev(heat.colors(5))[cut(meuse$lead,breaks=c(0,100,200,300,400,Inf),labels=FALSE)],
     col="grey",main="Lead Distribution", pch=21, axes=TRUE)

And we can transform the coordinates into something more useful (lon/lat).

library(rgdal)
proj4string(meuse) <- CRS("+init=epsg:28992")                   # set original projection
meuse <- spTransform(meuse, CRS("+proj=longlat +datum=WGS84"))  # transform to lon/lat
plot(meuse, pch=20, main="Full Dataset", axes=TRUE)
plot(meuse, 
     bg=rev(heat.colors(5))[cut(meuse$lead,breaks=c(0,100,200,300,400,Inf),labels=FALSE)],
     col="grey",main="Lead Distribution", pch=21, axes=TRUE)

And finally a counter-example, overlaying the points onto a Google map:

library(ggmap)    # loads ggplot2 as well
map <- get_map(location=rowMeans(bbox(meuse)), zoom=13)   # get Google map
ggmap(map) + 
  geom_point(data=as.data.frame(meuse), aes(x,y,fill=lead), 
             color="grey70", size=3.5, shape=21)+
  scale_fill_gradientn(colours=rev(heat.colors(5)))

What we've done here, in essence, is convert meuse from a data.frame to a spatialPointsDataFrame so that we could use spTransform(...) on the coordinates, then convert the result back to a data.frame so that we can use ggplot to overlay them onto a Google map.



来源:https://stackoverflow.com/questions/32229496/spatialpoints-and-spatialpointsdataframe

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!