R ::tmap plot and display NA values in legend - r

I want to map point data with results of bird counts. The point size should be scaled according to the number of birds that were counted. If an area has not been counted an x should be displayed for NA values. How do I plot these data and reach a nice legend with the tmap package?
This is a similar example:
rm(list=ls(all=TRUE))
library(tmap)
data(World, metro)
# put population size pop2020 to NA for some cities
metro$pop2020[10:300] <- NA
# add column with code for the shape of the symbol (21 for data available, 4 for NA)
metro$shape_symbol <- 21
metro[is.na(metro$pop2020), ]$shape_symbol <- 4
tm_shape(World) + tm_fill()+
tm_shape(metro) +
tm_symbols(
size = "pop2020",
col = "black",
shape = "shape_symbol", # use column shape_symbol in metro for the symbol
# shapeNA = "4", # should plot NA as cross by default - didnĀ“t work for me
title.size = "subtitle",
legend.size.is.portrait=TRUE) +
tm_layout(legend.bg.color = "gray",
legend.frame = "black")
Which gives this output. Why are the NA values not shown? And how do I reach a nice legend output?
My aim is to reach this:
The name of the bird species should be given as bold legend title with an additional label "Anzahl" for the legend symbols below. Ideally the symbol x for NA should be place like this. I can paste(i) from a loop as legend title with title.size but how do I get a second title in the legend.
Additional question: can I set the size of the points to a certain range? So that very small numbers have a minimum size in the map?

I solved it myself using a workaround:
I added an extra layer and selected only the data with missing values. Then I added an additional legend element using tm_add_legend.
data(World, metro)
# put population size pop2020 to NA for some cities
metro$pop2020[10:300] <- NA
tm_shape(World) + tm_fill()+
tm_shape(metro) +
tm_symbols(
size = "pop2020",
col = "black",
title.size = "subtitle",
legend.size.is.portrait=TRUE) +
tm_shape(metro[is.na(metro$pop2020),]) +
tm_dots(shape=4, size = 0.5, border.lwd = 0.5) +
tm_layout(legend.bg.color = "gray",
legend.frame = "black") +
tm_add_legend(type="symbol", shape =4, labels = "not available", size = 0.5, border.lwd = 0.5, col = "black")

Related

How to add centroids to an RDA plot

I'd like to replace the arrows on this RDA plot with centroids, something like what's pictured here.
This is the code I currently have which provides me arrows (I guess by default). I have shared our RDA code and I think this is where we might be able to change it from arrows to centroid:
# add arrows for effects of the expanatory variables
arrows(0,0, # start them from (0,0)
sc_bp[,1], sc_bp[,2], # end them at the score value
col = "red",
lwd = 1,
length = .1)
(but I share the entire code chunk (below), just in case.
Please note that my data is on fish community (species) and substrate types at 36 sites, I'd like to replace the arrows for substrates with centroids within my RDA.
##Now, the RDA
Y.mat<-Belt_2021_fish_transformed_forPCA #fish community
str(Y.mat)
X.mat<-Reefcheck_2021_forPCA #substrate
str(X.mat)
###Community data has already been transformed with hellinger
##Now, try the RDA
fish_substrate_rda<-rda(Y.mat,X.mat)
```
##Plot
## extract % explained by the first 2 axes
perc_b <- round(100*(summary(fish_substrate_rda)$cont$importance[2, 1:2]), 2)
## extract scores - these are coordinates in the RDA space
sc_si <- scores(fish_substrate_rda, display="sites", choices=c(1,2), scaling=1)
sc_sp <- scores(fish_substrate_rda, display="species", choices=c(1,2), scaling=1)
sc_sp <- sc_sp[c(2,7,8),]
sc_bp <- scores(fish_substrate_rda, display="bp", choices=c(1,2), scaling=1)
sc_bp <- sc_bp[c(2,5,6),]
# Set up a blank plot with scaling, axes, and labels
plot(fish_substrate_rda,
scaling = 1, # set scaling type
type = "none", # this excludes the plotting of any points from the results
frame = TRUE,
# set axis limits
ylim = c(-1.5,0.7),
xlim = c(-1.5,1.2),
# label the plot (title, and axes)
main = "Triplot RDA - scaling 1",
xlab = paste0("RDA1 (", perc_b[1], "%)"),
ylab = paste0("RDA2 (", perc_b[2], "%)")
)
# add points for site scores
points(sc_si,
pch = 21, # set shape (here, circle with a fill colour)
col = "black", # outline colour
bg = "steelblue", # fill colour
cex = 0.7) # size
# add points for species scores
points(sc_sp,
pch = 22, # set shape (here, square with a fill colour)
col = "black",
bg = "#f2bd33",
cex = 0.7)
# add text labels for species abbreviations
text(sc_sp + c(-0.09, -0.09), # adjust text coordinates to avoid overlap with points
labels = rownames(sc_sp),
col = "grey40",
font = 2, # bold
cex = 0.6)
# add arrows for effects of the expanatory variables
arrows(0,0, # start them from (0,0)
sc_bp[,1], sc_bp[,2], # end them at the score value
col = "red",
lwd = 1,
length = .1)
# add text labels for arrows
text(x = sc_bp[,1] -0.01, # adjust text coordinate to avoid overlap with arrow tip
y = sc_bp[,2] - 0.09,
labels = rownames(sc_bp),
col = "red",
cex = .7,
font = 1)
```
I have not found anything online that might help me to accomplish this.

Using BFAST to show breakpoints

I am currently working with bfastSpatial, I am attempting to plot breakpoint values as a year colour based legend. I am aware of changeMonth function for plotting monthly based breakpoints (http://www.loicdutrieux.net/bfastSpatial/) however, I am attempting to achieve a similar outcome as in Morrison et al. (2019) https://www.mdpi.com/2072-4292/10/7/1075
Any assistance would be appreciated.
If you want to round the breakpoint dates to integer years, you can use floor, as the dates are in decimal years. Next, to make a similar plot as the one you showed, you can use the tmap package. Since you did not attach any data to the OP, I used the tura data included in the bfastSpatial package.
library(bfastSpatial)
library(tmap)
# Load tura data
data(tura)
# Perform bfast analysis
bfm <- bfmSpatial(tura, start=c(2009, 1), order=1)
# Extract the first band (breakpoints)
change <- bfm[[1]]
# As breakpoints dates are in year decimals,
# you can use floor to round them to lowest integer
change <- floor(change)
# Set shape as change, the object to plot
tm_shape(change) +
# Plot it as raster and set the palette, number of categories,
# style (categorical) and title of the legend.
tm_raster(palette = "Spectral",
n = 5,
style = "cat",
title = "Year") +
# Set the legend's position and eliminate the comma used by default for
# separating thousands values. Add background color and transparency
tm_layout(legend.position = c("right", "bottom"),
legend.format=list(fun=function(x) formatC(x, digits=0, format="d")),
legend.bg.color = "white",
legend.bg.alpha = 0.7) +
# Add scale bar, set position and other arguments
tm_scale_bar(breaks = c(0,0.5,1),
position = c("right", "top"),
bg.color = "white",
bg.alpha = 0.7) +
# Add north arrow with additional parameters
tm_compass(type = "arrow",
position = c("left", "top"),
bg.color = "white",
bg.alpha = 0.7)
The obtained plot:

Manipulating "missing" label in legend: tmap

I want to manipulate the "Missing" label in my legend.
I'm using the tmap function in R. I want to change it to read "Missing or not eligible to gentrify"
I have tried using the tm_text function and considered how I would change the label in the underlying data, but haven't found a solution. Also, note the code uses a mapping function.
########################
# categorical mapping function
########################
cat.maps.wide.function <- function(data, varname, ltitle, colorplaette){
tm_shape(data, unit = "mi") +
tm_polygons(col = varname , # add variable(s)
style = "cat", # set break pattern to object LQ.cuts
palette = colorplaette, # set color fill to blue refreshing
border.col = "grey40", # color the borders white
border.alpha = 0.5, # set border transparency
title = ltitle, # title for legend
colorNA = "white") + # color of missing data
tm_style("bw") +
tm_layout(panel.label.bg.color ="NA",
frame = FALSE,
bg.color = "transparent") + # panel label color
tm_legend(legend.title.fontface = 2, # legend bold
legend.title.size = 0.75,
legend.text.size = 0.65,
legend.bg.alpha = 0,
legend.width = 5) +
tm_scale_bar(color.dark = "gray60", # Customize scale bar and north arrow
position = c(0.6, 0.05)) + # set position of the scale bar
tm_compass(type = "4star",
size = 2.5, # set size of the compass
fontsize = 0.5, # set font size of the compass
color.dark = "gray60", # color the compass
text.color = "gray60", # color the text of the compass
position = c(0.5, 0.05)) + # set position of the compass
# add border names
tm_shape(boro.boundaries) +
tm_borders(alpha = .5) +
tm_text("boro",
size = 0.75,
remove.overlap = TRUE,
auto.placement=FALSE,
xmod= "x", ymod= "y")
}
########################
# change in residential housing price
########################
# object for 2016 variable
mt1pva5.2016 <- cat.maps.wide.function(
data = data.map.tract.wide,
varname = "chgpcmt1pva5_overlap2016",
colorplaette = mt1pva5.overlap.colors,
ltitle = "Change in residential housing price for eligible tracts ")
mt1pva5.2016
Thanks for sharing the data. Apparently, you can use labels in tm_polygons but not to change the NA values. For that, you also will need textNA:
tm_polygons(col = varname , # add variable(s)
style = "cat", # set break pattern to object LQ.cuts
palette = colorplaette, # set color fill to blue refreshing
border.col = "grey40", # color the borders white
border.alpha = 0.5, # set border transparency
title = ltitle, # title for legend
colorNA = "white", # color of missing data
textNA = "Missing or not eligible to gentrify",
labels = c("Decrease in residential housing price",
"Increase in residential housing price")) +
...
the tm_layout() functin has the labels argument which lets you maniputale the label of the legend passing a character vector. In yout tm_layout add something like:
tm_layout(labels = c("Decrease in residential housing price",
"Increase in residential housing price",
"Missing or not eligible to gentrify")

In "R" during plotting "tmap" library places labels outside plotting region (partially)

I am importing shapefile into R and try to plot it with labels. Unfortunately some labels overlap. That's why I have to use parameter "auto.placement = T" for the "tm_text" function. But this parameter places some labels outside plotting region (partially). Position of labels on every plot is random. Sometimes labels are withing plotting region, but most of the times are not (cutted).
As you can see on screenshot "Palangos m." is cutted down to "angos m." and "Klaipedos m." is cutted down to "aipedos m.".
Screenshot: map
tm_shape(area_r1) +
tm_fill("winner", title = "Winner", style = "cat",
palette = c("#FFFFB3", "#1F78B4", "#1A9850", "#E7298A") ) +
tm_legend(text.size = 0.75) +
tm_layout("", legend.position = c("left", "bottom")) +
tm_borders("grey60") +
tm_layout(frame = F) +
tm_text("savivald", size = .65, col = "black", auto.placement = T)
What can I do in order to fit this labels into plotting region?
Controlling the randomness of auto.placement = T is difficult (though setting seed may help).
What you can do is adjusting the bounding box of your tmap object oh so slightly, so that there is more room on the left for the two or so missing letters.
Increasing the bbox by a half is probably an exaggeration, but you can tune it as required.
bbox_new <- st_bbox(area_r1) # current bounding box
xrange <- bbox_new$xmax - bbox_new$xmin # range of x values
yrange <- bbox_new$ymax - bbox_new$ymin # range of y values
bbox_new[1] <- bbox_new[1] - (0.5 * xrange) # xmin - left
# bbox_new[3] <- bbox_new[3] + (0.5 * xrange) # xmax - right
# bbox_new[2] <- bbox_new[2] - (0.5 * yrange) # ymin - bottom
# bbox_new[4] <- bbox_new[4] + (0.5 * yrange) # ymax - top
bbox_new <- bbox_new %>% # take the bounding box ...
st_as_sfc() # ... and make it a sf polygon
tm_shape(area_r1, bbox = bbox_new) +
tm_fill("winner", title = "Winner", style = "cat",
palette = c("#FFFFB3", "#1F78B4", "#1A9850", "#E7298A") ) +
tm_legend(text.size = 0.75) +
tm_layout("", legend.position = c("left", "bottom")) +
tm_borders("grey60") +
tm_layout(frame = F) +
tm_text("savivald", size = .65, col = "black", auto.placement = T)
I wrote a blog post summarizing the technique a while back. https://www.jla-data.net/eng/adjusting-bounding-box-of-a-tmap-map/
Your example is not exactly reproducible, but this image (making more space for the "big fat, title" on North Carolina map) should give you idea.
#Jinda Lacko has a creative solution using bbox , but for some reason it did not work for me. An easy solution is to use main.title in tm_layout, for example tm_layout(main.title = "Big Fat Title"). See this question for more details.

Change the legend on the color key of Heat Map in R

I have created the heatmap in R using HeatMaps.2. Everything went fine except the color key in my figure.
I'm plotting the expression values of genes in 'control' and 'case' conditions. In the final heatmap all upregualted genes have 'Red' in the 'case' condition and the downregulated genes have 'Green' in the 'case' condition which is perfect. But looking at the color key, Red shows low values and green shows high values.
In the legend of the color key, the value range is from 20-100 and the colors transitioning from 'red' to 'green'. I don't know how the Value's are calculated as my data has the values only from 2.0 - 13.0. This is how my code looks like:
my_palette <- colorRampPalette(c("red", "green"), (n=100))
heatmap.2(mat_data, Rowv=F, Colv=F, trace="none", dendrogram="none", density.info="none", key=TRUE,col=my_palette,
notecol="black",cexRow=0.45, cexCol=0.75,
offsetCol=0.5, symm=F,symkey=F, scale="none")
Could someone let me know how exactly these values are calculated and how can i invert these values to show 'red' high and 'green' low values?
I like to use ggplot.
# Package
require(ggplot)
# Sample data
mat_data = data.frame(x = rep(1:3,3), y = rep(1:3, each = 3), value = 1:9);
# Plot using ggplot
p <- ggplot(data = mat_data) + # Set data
geom_tile(aes(x = x, y = y, fill = value)) + # Define variables to plot
scale_fill_gradient(low = "red", high = "green") # Set colour scheme
# Display plot
p
See here for more a more detailed example.
Output from example:

Resources