Why do the error occurs adding legend to plot? - r

I'm trying to add the legend to my classification map using the code below.
library(raster)
library(RStoolbox)
landsat5 <- stack('lt05.tif')
shp<-shapefile("to5/to.shp")
SC_rf <- superClass(landsat5, shp, responseCol = "MC_ID",
nSamples = 1000, polygonBasedCV = TRUE,
model = "rf", tuneLength = 5, kfold = 5,
mode = "classification", predType = "raw", overwrite = TRUE)
## Plots
colors <- c("yellow", "green", "deeppink", "orange", "red")
plot(SC_rf$map, col = colors, legend = TRUE, axes = FALSE, box = FALSE)
legend(1, 1, legend = levels(shp$MC_info), fill = colors , title = "Classes")
The map is created but a legend error occurs:
'legend(1, 1, legend = levels(shp$MC_info), fill = colors, title = "Classes")':
'legend' is of length 0
Here is my shp object:

MC_info seems to be a vector, not a factor, so you don't need to use levels(). To access data in shapefile object, try to convert it by as.data.frame() function from raster package:
legend(1, 1, legend = raster::as.data.frame(shp)$MC_info, fill = colors , title = "Classes")
Or you can define a variable for that:
shp_df <- raster::as.data.frame(shp)
legend(1, 1, legend = shp_df$MC_info, fill = colors , title = "Classes")
This works for me as it converts the data data frame from the shp object and the MC_Info column is easily accessible. But I don!t have your data to check the legend working properly as you need...

Related

Plotting map points returning an unkwown output

Was constructing a series of plots for extracting bathymetric data and an rare output comes out when trying to generate the last b/w plot with my data. Here are my data coord (12sites_lat_long2.txt).
SITE,LAT,LONG
TAD,48.133119,-69.705842
IV,48.034772,-69.340821
LUD,49.161609,-68.173798
SAM,49.130887,-66.500031
NOR,50.163282,-66.467896
PUR,50.151276,-66.325630
NEW,48.263541,-64.735703
PAS,48.017946,-65.265587
BON,48.041124,-65.491133
COR,47.496607,-61.723938
ROO,47.806514,-61.232300
CAO,48.5058323,-64.2231551
And here my code were i downloaded the bathymetric set and ploted
library(marmap)
library(dplyr)
library(SoDA)
library(ade4)
library(adespatial)
library(ggmap)
library(ggplot2)
library(reshape2)
library(dartR)
library(BiocManager)
library(devtools)
library(plotly)
library(directlabels)
sites <- read.table("12sites_lat_long2.txt", header=TRUE,dec=".",sep=",")
#Order the site object and check the sites positions
sites <- sites %>% dplyr::arrange(SITE)
summary(sites)
#Keep only latitude and longitude info
sites_depth <- dplyr::select(sites,LONG,LAT)
#Get the bathimetric Data and build a matrix
#in this case, we get the data from NOAA using the marmap package
bathydata <- marmap::getNOAA.bathy(lon1= -70.2966,
lon2= -60.9692,
lat1= 51.2392,
lat2= 46.6170,
resolution = 1)
#Summarizing the data
summary(bathydata)
#Next, we extract the bathimetric data
#We plot map according to different levels of depth seting colors for each level
blues <- colorRampPalette(c("lightblue", "cadetblue2", "cadetblue1", "white"))
blues <- c("lightsteelblue4", "lightsteelblue3","lightsteelblue2", "lightsteelblue1")
greys <- c(grey(0.6), grey(0.93), grey(0.99))
#And Plot a map with the colors created
plot(bathydata, image = TRUE, land = TRUE, n=1,
bpal = list(c(0, max(bathydata), greys),
c(min(bathydata), 0, blues)))
#add the sampling points and text to the plot
points(sites$LON, sites$LAT, pch = 21, col = "black",
bg = "yellow", cex = 1.3)
text(sites$LON, sites$LAT,sites$SITE, pos = 2)
# plot a map without color
pdf("Marmap_saccharina.pdf")
plot(bathydata, lwd = c(0.3, 1), lty = c(1, 1),
deep = c(-4500, 0), shallow = c(-50, 0),
step = c(500, 0),
col = c("grey", "black"), drawlabels = c(FALSE, FALSE))
scaleBathy(bathydata, deg = 3, x = "bottomleft", inset = 5)
points(sites$LON, sites$LAT, pch = 21, col = "black", bg = "grey", cex = 1)
text(sites$LON, sites$LAT,sites$SITE, pos = 1,cex = 0.5)
dev.off()
The output that I get instead of the map is just
RStudioGD
2
I was expecting a map similar to this one
example
I have searched but have no clue what this output is refering to and were is the error

spplot legend with point rather than with scale

I am creating a plot based on INLA predictions. Everything works perfectly for the modelling, but for the plot,the legend on the graph are points (like https://gis.stackexchange.com/questions/350918/how-do-i-reverse-spplot-colour-key-so-the-values-are-decreasing) rather than a scale (like here http://www.nickeubank.com/wp-content/uploads/2015/10/RGIS3_MakingMaps_part1_mappingVectorData.html):
And here is the code that I would like to change. I guess there is a problem of factor (R spplot: colorbar rather than legend for SpatialPoint data, spplot issue with legend range and colors distribution) but I cannot understand how/what to change:
m_grid <- inla(formWITHOUT, data = inla.stack.data(region.stack.predGrid, spde = inlaSetting$region.spde),
family = "gamma",
control.predictor = list(A = inla.stack.A(region.stack.predGrid), compute = TRUE, link=1),
control.compute = list(cpo = TRUE, dic = TRUE),
control.family=list(link="default"))
summary(m_grid)
index.pred <- inla.stack.index(region.stack.predGrid, "region.pred")$data
region.grid_sf$Sbiomass <- m_grid$summary.fitted.values[index.pred, "mean"]
region.grid_sf$Sbiomass_sd <- m_grid$summary.fitted.values[index.pred, "sd"]
my.palette <- brewer.pal(n = 7, name = "OrRd")
par(mar = c(0,0,0,0))
spplot(region.grid_sf, c("Sbiomass"), col.regions = my.palette, col = "transparent")
Thanks in advance for any tips !
I finally found the answer:
cuts <- c(0,5000,10000,15000,20000,25000,30000)
spplot(region.grid_sf,
c("Sbiomass"),
col.regions = my.palette,
col = "transparent",
key.space = list(x=0.1,y=0.3),
colorkey =T,
cuts = cuts,
cex = 2,
pch = 22)

Plot colors change when exporting as SVG file in R

I am generating a figure for publishing that includes a heatmap and when I export it as .svg the colors change.
When I visualize it in R the colors look ok (heatmap colors match the legend colors):
However, after exporting it to svg the colors in the heatmap look dimmer:
I think it has something to do with the svg device including a "white border" to every row of the heatmap, as the colors in the legend are unaffected. If you zoom in very closely you can appreciate it:
I am using the following code to export them. I have tried changing the bg and antialias parameteres of svg but there is no change:
svg(filename="test.svg",width = 10, height = 5)
Figure3
dev.off()
When I export is as pdf, the colors are ok:
I guess I will export them as .pdf but I would like to know what is causing this more as a curiosity.
Thanks!
Edit: added dataset and code to generate the plot:
From the package documentation, default colors for the heatmap are generated as:
colorRamp2(seq(min(mat), max(mat), length = 3), c("blue", "#EEEEEE", "red"))
For the blocks in the left I used another palette in the initial example, here I use RColorBrewer and it has the same effect.
I dont think it's a problem of the color palette as it is ok in the legend, I guess it's a problem of a "border" around each row (both the blocks and the heatmap colors are defined as rows of a tile).
Dataset:
https://file.io/l6fL28Cy
Code:
library(ComplexHeatmap)
library(RColorBrewer)
Import data:
x = readRDS("data.rds")
#Select number of clusters to plot:
clusters = 7
#Generate dendrogram to make block annotation:
dend = as.dendrogram(hclust(as.dist(1- cor(t(x))),"complete"), hang=-1)
#Create annotation block for heatmap
cl_num = cutree(dend, k = clusters)
cl_col = brewer.pal(clusters,"Set2")
names(cl_col) = unique(cl_num)
cl_col = list(cl_num=cl_col)
row_ha = rowAnnotation(cl_num = cl_num,
col = cl_col,
annotation_legend_param = list(title = "Cluster"),
show_annotation_name = F)
###Create heatmap:
Heatmap(x,
clustering_distance_columns = "euclidean",
clustering_method_columns = "complete",
clustering_distance_rows = "pearson",
clustering_method_rows = "complete",
row_split = clusters,
left_annotation = row_ha,
show_row_names = F,
heatmap_legend_param = list(title = "Z-score"),
column_title = "Treatment",
row_title = "Genes",
use_raster = F,
column_dend_height = unit(0.1, "cm"),
column_names_gp = gpar(fontsize = 16),
column_names_rot = 0,
column_names_centered = TRUE)

contourplot color and labels options in Lattice for R

I am quite new to Lattice and I am stuck with some possibly basic coding. I am using shapefiles and geoTIFFS to produce maps of animals distribution and in particular I have:
1 x point shapefile
2 x geoTIFF
1 x polygon shapefile
I am overlapping a levelplot of one of the geoTIFF (UD generated with adehabitatHR) with a contourplot of the same geoTIFF at specific intervals (percentile values), a contourplot of the second geoTIFF (depth raster from ETOPO2) for three specific values (-200, -1000 and -2000), the point shapefile (animal locations) and the polygon shapefile (land). All works fine but I need to change the font size of contour plot labels, their length (i.e. from 0.12315 to 0.123) and positioning for all the contourplots. For the depth contourplot I would like to change the style of each line in something like "continous line", "dashed line" and "point line", and for the contourplot of the UD I would like to change the color of each line using a yellow to red palette.
As far as I understand, I should use panel functions to implement these changes (e.g. Controlling z labels in contourplot) but i am not quite sure how to do it. Part of my code to generate the "plot":
aa <-
quantile(
UD_raster,
probs = c(0.25, 0.75),
type = 8,
names = TRUE
)
my.at <- c(aa[1], aa[2])
depth<-c(-100, -200, -2000)
levelplot(
UD_raster,
xlab = "",
ylab = "",
margin = FALSE,
contour = FALSE,
col.regions = viridis(100),
main = "A",
maxpixels = 2e5
) + layer(sp.polygons(Land, fill = "grey40", col = NA)) + layer(sp.points(locations, pts = 2, col = "red")) + contourplot(
UD_raster,
at = my.at,
labels = TRUE,
margin = FALSE
) + contourplot(
ETOPO2,
at = depth,
labels = TRUE,
margin = FALSE
)
A simplified image, with no UD layer and no point shapefile can be found here and as you can see it is pretty messy. Thanks for your help.
So far for the ETOPO2 countourplot I have solved by eliminating the labels and adding the argument lty to style the line. Because I can't figure out how to use lty with different values for each single line in my contour, I have replicated the contourplot function three times on the same surface, one for each contour I am interested into (this was easy because I only need three contours).
For the position, font and font size of the labels of the remaining contourplot I have used
labels = list(cex = 0.8, "verdana"),
label.style = "flat"
To "shorten" the length of the labels I have used the function round where I specify to which decimal digit to round number.
So now my new code looks like:
aa <-
quantile(
UD_raster,
probs = c(0.25, 0.75),
type = 8,
names = TRUE
)
my.at <- c(aa[1], aa[2])
my.at <- round(my.at, 3)
levelplot(
UD_raster,
xlab = "",
ylab = "",
margin = FALSE,
contour = FALSE,
col.regions = viridis(100),
main = "A",
maxpixels = 2e5
) + layer(sp.polygons(Land, fill = "grey40", col = NA)) + layer(sp.points(positions, pts = 2, col = "red")) + contourplot(
UD_raster,
at = my.at,
labels = list(cex = 0.8, "verdana"),
label.style = "flat",
margin = FALSE
) + contourplot(
ETOPO2,
at = -200,
labels = FALSE,
margin = FALSE,
lty = 1,
pretty = TRUE
) + contourplot(
ETOPO2,
at = -1000,
labels = FALSE,
margin = FALSE,
lty = 2,
pretty = TRUE
) + contourplot(
ETOPO2,
at = -2000,
labels = FALSE,
margin = FALSE,
lty = 3,
pretty = TRUE
)
As one could expect, it takes a bit longer to produce the plot. Still no idea on how to change the colors of the UD contourplot.

How to plot a table of values and corresponding colors in R? The dreaded heat map [duplicate]

I am trying to create a data table whose cells are different colors based on the value in the cell. I can achieve this with the function addtable2plot from the plotrix package. The addtable2plot function lays a table on an already existing plot. The problem with that solution is that I don't want a plot, just the table.
I've also looked at the heatmap functions. The problem there is that some of the values in my table are character, and the heatmap functions, from what I can tell, only accept numeric matrices. Also, I want my column names to be at the top of the table, not the bottom, and that doesn't seem to be an option.
Here's the example code for addtable2plot. If I could get just the table, filling the whole screen, that would be great.
library(plotrix)
testdf<-data.frame(Before=c(10,7,5,9),During=c(8,6,2,5),After=c(5,3,4,3))
rownames(testdf)<-c("Red","Green","Blue","Lightblue")
barp(testdf,main="Test addtable2plot",ylab="Value",
names.arg=colnames(testdf),col=2:5)
# show most of the options including the christmas tree colors
abg<-matrix(c(2,3,5,6,7,8),nrow=4,ncol=3)
addtable2plot(2,8,testdf,bty="o",display.rownames=TRUE,hlines=TRUE,
vlines=TRUE,title="The table",bg=abg)
Any help would be greatly appreciated.
A heatmap alternative:
library(gplots)
# need data as matrix
mm <- as.matrix(testdf, ncol = 3)
heatmap.2(x = mm, Rowv = FALSE, Colv = FALSE, dendrogram = "none",
cellnote = mm, notecol = "black", notecex = 2,
trace = "none", key = FALSE, margins = c(7, 11))
In heatmap.2 the side of the plot the axis is to be drawn on is hard-coded. But if you type "heatmap.2" at the console and copy the output to an editor, you can search for axis(1, where the 1 is the side argument (two hits). You can then change from a 1 (axis below plot) to a 3 (axis above the plot). Assign the updated function to a new name, e.g. heatmap.3, and run it as above.
An addtable2plot alternative
library(plotrix)
# while plotrix is loaded anyway:
# set colors with color.scale
# need data as matrix*
mm <- as.matrix(testdf, ncol = 3)
cols <- color.scale(mm, extremes = c("red", "yellow"))
par(mar = c(0.5, 1, 2, 0.5))
# create empty plot
plot(1:10, axes = FALSE, xlab = "", ylab = "", type = "n")
# add table
addtable2plot(x = 1, y = 1, table = testdf,
bty = "o", display.rownames = TRUE,
hlines = TRUE, vlines = TRUE,
bg = cols,
xjust = 2, yjust = 1, cex = 3)
# *According to `?color.scale`, `x` can be a data frame.
# However, when I tried with `testdf`, I got "Error in `[.data.frame`(x, segindex) : undefined columns selected".
A color2D.matplot alternative
library(plotrix)
par(mar = c(0.5, 8, 3.5, 0.5))
color2D.matplot(testdf,
show.values = TRUE,
axes = FALSE,
xlab = "",
ylab = "",
vcex = 2,
vcol = "black",
extremes = c("red", "yellow"))
axis(3, at = seq_len(ncol(testdf)) - 0.5,
labels = names(testdf), tick = FALSE, cex.axis = 2)
axis(2, at = seq_len(nrow(testdf)) -0.5,
labels = rev(rownames(testdf)), tick = FALSE, las = 1, cex.axis = 2)
After this little exercise, I tend to agree with #Drew Steen that LaTeX alternatives may be investigated as well. For example, check here and here.
You can hack something with grid and gtable,
palette(c(RColorBrewer::brewer.pal(8, "Pastel1"),
RColorBrewer::brewer.pal(8, "Pastel2")))
library(gtable)
gtable_add_grobs <- gtable_add_grob # alias
d <- head(iris, 3)
nc <- ncol(d)
nr <- nrow(d)
extended_matrix <- cbind(c("", rownames(d)), rbind(colnames(d), as.matrix(d)))
## text for each cell
all_grobs <- matrix(lapply(extended_matrix, textGrob), ncol=ncol(d) + 1)
## define the fill background of cells
fill <- lapply(seq_len(nc*nr), function(ii)
rectGrob(gp=gpar(fill=ii)))
## some calculations of cell sizes
row_heights <- function(m){
do.call(unit.c, apply(m, 1, function(l)
max(do.call(unit.c, lapply(l, grobHeight)))))
}
col_widths <- function(m){
do.call(unit.c, apply(m, 2, function(l)
max(do.call(unit.c, lapply(l, grobWidth)))))
}
## place labels in a gtable
g <- gtable_matrix("table", grobs=all_grobs,
widths=col_widths(all_grobs) + unit(4,"mm"),
heights=row_heights(all_grobs) + unit(4,"mm"))
## add the background
g <- gtable_add_grobs(g, fill, t=rep(seq(2, nr+1), each=nc),
l=rep(seq(2, nc+1), nr), z=0,name="fill")
## draw
grid.newpage()
grid.draw(g)
Sort of a hacky solution based on ggplot2. I don't totally understand how you actually want to map your colors, since in your example the colors in the table are not mapped to the rownames of testdf, but here I've mapped the colors to the value (converted to a factor).
testdf$color <- rownames(testdf)
dfm <- melt(testdf, id.vars="color")
p <- ggplot(dfm, aes(x=variable, y=color, label=value, fill=as.factor(value))) +
geom_text(colour="black") +
geom_tile(alpha=0.2)
p
You can change what variable the values are mapped to using fill=, and you can change the mapping using scale_fill_manual(values=[a vector of values].
That said, I'd be curious to see a solution that produces an actual table, rather than a plot masquerading as a table. Possibly using Sweave and LaTeX tables?

Resources