Legend of a raster map with categorical data - r

I would like to plot a raster containing 4 different values (1) with a categorical text legend describing the categories such as 2 but with colour boxes:
I've tried using legend such as :
legend( 1,-20,legend = c("land","ocean/lake", "rivers","water bodies"))
but I don't know how to associate one value to the displayed color. Is there a way to retrieve the colour displayed with 'plot' and to use it in the legend?

The rasterVis package includes a Raster method for levelplot(), which plots categorical variables and produces an appropriate legend:
library(raster)
library(rasterVis)
## Example data
r <- raster(ncol=4, nrow=2)
r[] <- sample(1:4, size=ncell(r), replace=TRUE)
r <- as.factor(r)
## Add a landcover column to the Raster Attribute Table
rat <- levels(r)[[1]]
rat[["landcover"]] <- c("land","ocean/lake", "rivers","water bodies")
levels(r) <- rat
## Plot
levelplot(r, col.regions=rev(terrain.colors(4)), xlab="", ylab="")

By default, the colours used in a raster-plot are generated by rev(terrain.colors()) (see ?raster::plot). You can use this to re-create that sequence of 4 colours for your legend - or choose a random sequence of colours:
my_col = rev(terrain.colors(n = 4))
# my_col = c('beige','red','green','blue')
First plot the map using the colour sequence. legend = FALSE gets rid of the standard colour bar:
plot(my_raster, legend = FALSE, col = my_col)
Add a custom legend to the bottom left. Use the fill argument to generate coloured boxes:
legend(x='bottomleft', legend = c("land", "ocean/lake", "rivers", "water bodies"), fill = my_col)

Related

Plot3d only plots first two principle components

I am currently trying to plot the colours of different subgroups of a large dataset. I have separated the data in to 6 subgroups with 6 colours. However my plot3d function only plots the first two principle components.
Here is the example of the plot.
Here is the code. I have create a PCA analysis of my dataset and originally only want to show the first 3 main principle components but I have tried plotting all the principle components to ensure it isn't to do with the data.
PCA_Model <- prcomp(t(Input_dataset), center = T, scale=F)
samples_names <- row.names(PCA_Model$rotation)
# Bind sample names to their subgroup
pca_matrix <- cbind(samples_names, "Subgroup"=labeled_subgroup, stringsAsFactors=FALSE)
# Link dataframe to color
colours <- as.character(factor(pca_matrix[,"Subgroup"], levels = paste0("C", 1:6),labels = c("blue",
"red", "yellow", "green", "black", "white")))
plot3d(PCA_Model$x[,1:440], col=colours)
The dataset is very diverse so should show all subgroups. Any help would be much appreciated!
You may be using the wrong plotting function. Using scatter3d in the latest version of plot3D package:
# fit PCA model
PCA_Model <- prcomp(dplyr::select(iris, -Species), center = T, scale=F)
# Plot
scatter3D(x = PCA_Model$x[,1], y = PCA_Model$x[,2], z = PCA_Model$x[,3],
# just use the factor to color the points:
col = factor(iris$Species))
I think you get something odd from feeding characters into the col option of plot3d. So below I show an example of how to feed the colors. You create a color vector first, named it after your levels and then call them out. Adjust the script before for 6 colours:
library(rgl)
library(RColorBrewer)
pca = prcomp(iris[,-5])$x
COLS = brewer.pal(3,"Set1")
names(COLS) = levels(iris$Species)
plot3d(pca,col=COLS[as.character(iris$Species)])
I used snapshot3d() to capture the image, and the axis labels seem quite squished

R plot3d coloring

I am using plot3d() from rgl to make 3D scatter plots, using three columns, of samples in a data frame. Furthermore, I am using a fourth column colorby from my data frame (where each sample takes values, say, 10, 11, 12 as factors/levels) to color the points in the plot.
When using plot() to make 2D plots, I first set palette(rainbow(3)) and then col = colorby within plot() followed by legend(). The plot, colors and legend work fine.
However, when I repeat the last part for plot3d(), the coloring mixes up and not the same colors are assigned to the same levels as they would be in plot(). Moreover, if I use legend3d("topright", legend = levels(colorby), col = rainbow(3)) to create a legend, it looks the same as the 2D legend, but the coloring is clearly wrong in the 3D plot.
Where am I going wrong?
This looks correct to me:
df <- data.frame(x=1:9, y=9:1, z=101:109, colorby=gl(3,3))
palette(rainbow(3))
plot(x~y, df, col = df$colorby)
library(rgl)
with(df, plot3d(x,y,z, col = colorby))
legend3d("topright", legend = levels(df$colorby), col = levels(df$colorby), pch=19)

How to add colour matched legend to a R matplot

I plot several lines on a graph using matplot:
matplot(cumsum(as.data.frame(daily.pnl)),type="l")
This gives me default colours for each line - which is fine,
But I now want to add a legend that reflects those same colours - how can I achieve that?
PLEASE NOTE - I am trying NOT to specify the colours to matplot in the first place.
legend(0,0,legend=spot.names,lty=1)
Gives me all the same colour.
The default color parameter to matplot is a sequence over the nbr of column of your data.frame. So you can add legend like this :
nn <- ncol(daily.pnl)
legend("top", colnames(daily.pnl),col=seq_len(nn),cex=0.8,fill=seq_len(nn))
Using cars data set as example, here the complete code to add a legend. Better to use layout to add the legend in a pretty manner.
daily.pnl <- cars
nn <- ncol(daily.pnl)
layout(matrix(c(1,2),nrow=1), width=c(4,1))
par(mar=c(5,4,4,0)) #No margin on the right side
matplot(cumsum(as.data.frame(daily.pnl)),type="l")
par(mar=c(5,0,4,2)) #No margin on the left side
plot(c(0,1),type="n", axes=F, xlab="", ylab="")
legend("center", colnames(daily.pnl),col=seq_len(nn),cex=0.8,fill=seq_len(nn))
I have tried to reproduce what you are looking for using the iris dataset. I get the plot with the following expression:
matplot(cumsum(iris[,1:4]), type = "l")
Then, to add a legend, you can specify the default lines colour and type, i.e., numbers 1:4 as follows:
legend(0, 800, legend = colnames(iris)[1:4], col = 1:4, lty = 1:4)
Now you have the same in the legend and in the plot. Note that you might need to change the coordinates for the legend accordingly.
I like the #agstudy's trick to have a nice legend.
For the sake of comparison, I took #agstudy's example and plotted it with ggplot2:
The first step is to "melt" the data-set
require(reshape2)
df <- data.frame(x=1:nrow(cars), cumsum(data.frame(cars)))
df.melted <- melt(df, id="x")
The second step looks rather simple in comparison to the solution with matplot
require(ggplot2)
qplot(x=x, y=value, color=variable, data=df.melted, geom="line")
Interestingly #agstudy solution does the trick, but only for n ≤ 6
Here we have a matrix with 8 columns. The colour of the first 6 labels are correct.
The 7th and 8th are wrong. The colour in the plots restarts from the beginning (black, red ...) , whereas in the label it continues (yellow, grey, ...)
Still haven't figured out why this is the case. I'll maybe update this post with my findings.
matplot(x = lambda, y = t(ridge$coef), type = "l", main="Ridge regression", xlab="λ", ylab="Coefficient-value", log = "x")
nr = nrow(ridge$coef)
legend("topright", rownames(ridge$coef), col=seq_len(nr), cex=0.8, lty=seq_len(nr), lwd=2)
Just discovered that matplot uses linetypes 1:5 and colors 1:6 to establish the appearance of the lines. If you want to create a legend try the following approach:
## Plot multiple columns of the data frame 'GW' with matplot
cstart = 10 # from column
cend = cstart + 20 # to column
nr <- cstart:cend
ltyp <- rep(1:5, times=length(nr)/5, each=1) # the line types matplot uses
cols <- rep(1:6, times=length(nr)/6, each=1) # the cols matplot uses
matplot(x,GW[,nr],type='l')
legend("bottomright", as.character(nr), col=cols, cex=0.8, lty=ltyp, ncol=3)

Border cells in heatmap

I am trying to construct a heatmap in R using a correlation matrix and a p value matrix.
I use this tutorial to build the heatmap without problems. It works perfectly. I can even introduce some values from a second matrix (the p value matrix) in the right cells.
But when I try to highlight the corresponding cells it doesn't work. I use this code to generate the borders.
I use RStudio v0.97 with the packages gplots, RColorBrewer.
The code is :
library(gplots)
library(RColorBrewer)
my_palette <- colorRampPalette(c("red", "yellow", "green"))(n = 299)
nx = 5
ny = 10
mat1 <- matrix(rnorm(nx*ny,100,50),nx,ny)
mat2 <- mat1>150 #matrix used for the example instead of the p value matrix
makeRects <- function(tfMat,border){
cAbove = expand.grid(1:nx,1:ny)[tfMat,]
xl=cAbove[,1]-0.49
yb=cAbove[,2]-0.49
xr=cAbove[,1]+0.49
yt=cAbove[,2]+0.49
rect(xl,yb,xr,yt,border=border,lwd=3)
} #this is the function to make the rectangles/borders
heatmap.2(mat1,
Rowv = FALSE, # don't reorganize columns
cellnote = mat2, # check correspondance between rectangles and mat2 values
main = "Correlation", # heat map title
notecol="black", # change font color of cell labels to black
notecex=0.5, # change the scaling of the cell labels
density.info="none", # turns off density plot inside color legend
trace="none", # turns off trace lines inside the heat map
margins =c(12,9), # widens margins around plot
col=my_palette, # use on color palette defined earlier
dendrogram="row", # don't draw a row dendrogram
Colv="NA", # turn off column clustering
add.expr = {makeRects(mat2,"black")}) #add the borders
I think something is wrong either with the makeRects function, or with the re-ordering of the rows via the heatmap.2 function. The rectangles appear in the heatmap, but they are not at the right positions. I have been scratching my head all day without finding what is wrong.
Any suggestions?

How to create legend to a scatter plot with scaled points: [R]

I have created a scatter plot with circle size changing with the intensity of the data: Fro 0 to 2, from 2 to 4,.. from 8 to 10. Does anyone could help me to create the proper legend for my plot?.
My code is:
require(xlsx)
data <- read.xlsx("data.xlsx", 1, header=TRUE) # reading the data
BRfunc <- colorRampPalette(c("blue", "red")) # the color gradient
itvl <- c(0,2,4,6,8,10)
plot(data$years, data$cars, cex=findInterval(data$emission, itvl), col="black" )
I've created a reproducible data set
n <- 50
data <- data.frame(years=1950+(1:n), cars=rnorm(n), emission=runif(n,0,10))
Then use your code to plot the figure
itvl <- c(0,2,4,6,8,10)
plot(data$years, data$cars, cex=findInterval(data$emission, itvl), col="black" )
To be able to create the legend, I've used legend() as Marc in the box suggested.
legend("topright", legend=itvl, pt.cex=itvl, pch=1)
You can use options such as xjust and x.intersp to change the spacing between the symbols and legend. You can use bty to remove the box.

Resources