5

I would like to use the raster attribute table information to create the legend of a raster such as the raster 1 and display the legend only for the class displayed in the raster. I build an example to explain what I would like to get.

1/ Build the raster

r <- raster(ncol=10, nrow=10)
values(r) <-sample(1:3,ncell(r),replace=T)

2/ Add the Raster Attribute Table

r <- ratify(r) # build the Raster Attibute table
rat <- levels(r)[[1]]#get the values of the unique cell frot the attribute table
rat$legend <- c('Class A', 'Class B', 'Class C')
levels(r) <- rat

3/ Plot the raster Fig 1

my_col=c('blue','red','green')
plot(r,col=my_col,legend=F,box=F,axes=F)
legend(x='top', legend =rat$legend,fill = my_col)

I would like to replace the legend =rat$legend parammeter by a properties of the raster linked to the ratser attribute table. I have tried different combination using levels() such as c(levels(r)[[1]][1]) but I generate a list and not a character not usable in the legend parameter.

4/ Crop and plot the raster to a part with only 2 classes (here the 4 pixels at the down right extent) Fig 2

rcrop<-crop(r,extent(r,9,10,9,10))
plot(rcrop,col=my_col,legend=F,box=F,axes=F)

For this second fig, I thus would like to diplay automatically only the legend of the class displayed on the raster 2.

Raster with legend

Cropped raster with legend


Here is the solution proposed by Roman 4. Solution proposed by Roman

Wraf
  • 747
  • 2
  • 10
  • 24
  • Roman's answer is good; just wanted to point out that if you have a `list` and want a character vector, you can always do `as.character(unlist(mylist))` – Carl Witthoft Oct 25 '13 at 11:41
  • @Carl : Thanks, indeed when I use 'legend(x='top', legend =as.character(unlist( c(levels(r)[[1]][2]))),fill = my_col)' , I directly get the legend from the attribute raster table. Anyway, the Roman's answer does not solve the problem as it create a new legend not based on the raster attribute table. I'm thus losing the 'Class A',... legend – Wraf Oct 25 '13 at 11:47

3 Answers3

2

If you are willing to use lattice graphics, the levelplot method defined in the rasterVis package is able to display categorical data with a legend based on the RAT:

library(raster)
library(rasterVis)

r <- raster(ncol=10, nrow=10)
values(r) <- rep(1:4, each=25)

r <- ratify(r) 
rat <- levels(r)[[1]]
rat$legend <- c('Class A', 'Class B', 'Class C', 'Class D')
levels(r) <- rat

levelplot(r)

rat.png

Besides, I have commited some changes in the development version available at GitHub to manage a Raster* whose RAT levels are not all present in the data:

rcrop <- crop(r,extent(r,6,10,1,10))
levelplot(rcrop)

rat crop

rcrop <- crop(r,extent(r,1,5,1,10))
levelplot(rcrop)

rat crop2

Oscar Perpiñán
  • 4,491
  • 17
  • 28
  • 1
    @ Oscar:Thanks for your answer and the changes to ratserVis. I think it could be interesting to link the rat to a color as it is usefull to plot the same color for the same value. I thus add a column color in the rat. – Wraf Oct 29 '13 at 08:39
  • @Wraf: I agree, is is better to keep colors for each class. A manual solution is to define `col.regions` or `par.settings` in each `levelplot` call. It would be better to use the content of the `legend` slot of the `RasterLayer` object, but it is not implemented in `levelplot` yet. – Oscar Perpiñán Oct 30 '13 at 11:01
1

Maybe query the rcrop raster to find out which are the levels in the cropped raster and pass that to the legend?

legend(x = 'top', legend = unique(getValues(rcrop)), fill = my_col)
Roman Luštrik
  • 69,533
  • 24
  • 154
  • 197
  • @ Roman : Using your proposition allows to have a legend with only 2 classes but doesn't allow to use the Raster Attribute Table giving not the graph expected. I add the result I got with what you proposed in my question. – Wraf Oct 25 '13 at 11:51
  • Try x<-data.frame(levels(rcrop)), x[unique(getValues(rcrop)),2] – DJack Oct 25 '13 at 12:34
1

Thanks. Based on what you proposed I found a solution:

plot(rcrop,col=my_col[unique(getValues(rcrop))],legend=F,box=F,axes=F)
legend_full<-data.frame(levels(rcrop))
legend(x='top', legend =as.character(unlist(legend_full[unique(getValues(rcrop)),2])),fill = my_col[unique(getValues(rcrop))])

It works and allows to be independent of the values displayed in the raster.

Wraf
  • 747
  • 2
  • 10
  • 24