4

I have some kind of noob question: how do I plot spatialpoints dataframe in R using spplot (or ggmap) based on column values?

let's say we have this:

library(sp)
data(meuse)

v <- SpatialPointsDataFrame(meuse, coords = meuse[,1:2])

How would I plot 'copper' column here (with triangles pointed up or down based on a random threshold - let's say 31.0)?

I couldn't find a specific anwser so far.

Or how do I do that using proportional symbols?

2 Answers 2

5

Converting the data to an sf object, you can either use ggplot as the answer before or ggmap in the following way:

library(sp)
library(sf)
#> Linking to GEOS 3.6.1, GDAL 2.2.3, PROJ 4.9.3
library(dplyr, warn.conflicts = F)
library(ggmap, quietly = T)

data('meuse')
coordinates(meuse) <- ~x+y
proj4string(meuse) <- CRS("+init=epsg:28992")

meuse <- st_as_sf(meuse,coords = 1:2)

meuse <- meuse %>% 
  st_transform(crs = 4326)

meuse_map <- get_stamenmap(
   bbox = unname(st_bbox(meuse)),
   zoom = 13, maptype = 'toner-lite', source = 'stamen'
 ) %>% ggmap()
#> Map from URL : http://tile.stamen.com/toner-lite/13/4226/2742.png
#> Map from URL : http://tile.stamen.com/toner-lite/13/4227/2742.png
#> Map from URL : http://tile.stamen.com/toner-lite/13/4226/2743.png
#> Map from URL : http://tile.stamen.com/toner-lite/13/4227/2743.png
#> Map from URL : http://tile.stamen.com/toner-lite/13/4226/2744.png
#> Map from URL : http://tile.stamen.com/toner-lite/13/4227/2744.png

meuse_map + 
  geom_sf(
    data = meuse, 
    aes(size = copper), 
    color = 'red', alpha = 0.5,
    show.legend = 'point', inherit.aes = F
  )
#> Coordinate system already present. Adding new coordinate system, which will replace the existing one.

meuse <- meuse %>% mutate(copper.shape = ifelse(copper > 31, '> 31', '<= 31'))

meuse_map + 
  geom_sf(
    data = meuse, 
    aes(shape = copper.shape, fill = copper.shape), 
    inherit.aes = F
  ) +
  scale_shape_manual(values = c(25,24), guide = F) +
  scale_fill_manual(values = c('green','red'))
#> Coordinate system already present. Adding new coordinate system, which will replace the existing one.

2
  • Good answer - well illustrated!
    – Simbamangu
    Feb 18, 2019 at 4:42
  • nice, best representation so far. Thank you! Feb 18, 2019 at 8:31
3

For threshold:

plot(v[v$copper>31,], pch = 2, col="blue")
points(v[v$copper<=31,], pch = 6, col="red")

For proportional:

plot(v, cex=(3*(v$copper)/max(v$copper)), pch=16)

Apologies; ggplot for shape:

v@data$threshold = ifelse(v$copper > 31, "a", "b")
ggplot(data=v@data,
       aes(x=x,y=y, shape = threshold)) +
  geom_point() +
  scale_shape_manual(values=c(2,6))

ggplot code for proportional:

ggplot(data=v@data,
       aes(x=x,y=y, size = copper)) +
  geom_point()

Upon reflection, I think you'd be better off making a call to the coordinates slot rather than x and y from v. This is because x and y are fixed in the dataframe part of the SpatialPointsDataFrame. Instead, doing something like what I have below plots based on the spatial part of things and is robust to transformations on the object.

# Assume a sample spatial argument for the dataframe
proj4string(v) = CRS("+proj=utm +zone=10 +ellps=GRS80 +datum=NAD83 +units=m +no_defs")
proj4string(v)
# spatial transformation
v2 = spTransform(v,
                 CRSobj = CRS("+init=epsg:4326"))
proj4string(v2)

# Plotting this way enables plotting based on transformations
ggplot(data=v2@data,
       aes(x=coordinates(v2)[,1],y=coordinates(v2)[,2], 
           shape = threshold)) +
  geom_point() +
  scale_shape_manual(values=c(2,6)) 
1
  • 3
    That's base graphics - not spplot or ggplot.
    – Spacedman
    Feb 15, 2019 at 22:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.