tflutre tflutre - 1 month ago 17
R Question

distinguish spatial points by two attributes (via color and symbol) with spplot

Let's say we are interested in comparing 9 different cultivars of a plant species, by planting 2 cuttings of each of them in a field. I want to plot the whole layout, with one point per cutting, as if we were seeing the field from above. With the

R packages, I know how to use colors to distinguish cuttings according to one factor attribute, but I can't succeed in also using symbols for another factor attribute.

More details are needed to understand the reproducible example below. I further assume that the cuttings were planted on a regular grid with 6 rows and 3 columns (18 locations in total). The field is divided into 2 blocks of 9 locations each, so that each cultivar is present only once in each block. So I want to use color to distinguish the blocks (say, block A in blue and block B in red). Moreover, the cultivars belong to two different categories. I hence also want to use symbols to distinguish categories (say, circles and triangles).

(x <- data.frame(cultivar=rep(paste0("cv", 1:9), 2),
row=rep(11:16, each=3),
column=rep(5:7, 6),
block=rep(c("A","B"), each=9),
category=rep(c(5,5,rep(1,7)), 2)))

Such a data.frame can be converted into a spatial object:

x.sp <- SpatialPointsDataFrame(coords=x[,c("column","row")],

Here is how I manage to distinguish blocks per color:

spplot(obj=x.sp, zcol=c("block"),
scales=list(draw=TRUE), aspect="fill",
main="Layout on the field")


When I specify
, the error says:
all factors should have identical levels

I read about the
option of
, and the
option of
(called by
), but don't quite understand how they work. Any idea?

Or do you know of another (easy) way to do such a plot with other packages?


I shows two approaches, using update and making additional factor.

The foarmer: First, you make a base object having a "block" (color) information (it is almost the same as what you showed above). Second, you can add "category" (pch) information and legend using update().

The latter: It is based on the idea that make and use combination factor having all factorial information.

  ## "category" isn't numeric but factor. It would be better to change class.
x$category <- as.factor(x$category)
x.sp <- SpatialPointsDataFrame(coords=x[,c("column","row")], data=x[,c("block","category")])

  ## make a base graph ("block")
p <- spplot(obj = x.sp, zcol = c("block"),
            col.regions = c("blue","red"), = "none", # <- modify not to make legend
            scales = list(draw=TRUE), aspect = "fill",
            xlab = colnames(coordinates(x.sp))[1],
            ylab = colnames(coordinates(x.sp))[2],
            main = "Layout on the field")

  ## add "category" information and legend
p <- update(p, pch = c(16, 17)[x.sp$category],
            key = list(right = list(fun = draw.key), 
                       points = list(col = c("red", "blue", 1, 1), pch = c(15, 15, 1, 2)), 
                       text = list(c(levels(x.sp$block), levels(x.sp$category))),
                       space = 'right', columns = 1)) 

enter image description here

The latter approach (using combination of factor)

x.sp2 <- SpatialPointsDataFrame(coords=x[,c("column","row")], 
                                data=cbind(x[,c("block","category")], comb = paste0(x$block, x$category)))

spplot(x.sp2, "comb", col.regions = rep(c("red", "blue"), each = 2), pch = rep(c(16, 17), 2), 
       scales=list(draw=TRUE), aspect="fill", = "right",
       main="Layout on the field")