R tmap:: inner margins appear although set to zero - r

I am creating a map that consists out of 3 map panels. I have set the inner margins to zero in the tm_layout options for all maps, however depending on the dimensions of the output I still have empty white space inside the map frames.
I can reduce it to a minimum if I adjust the setting for width and height with tm_save but I want a clean solution.
I tried to creat a minimum example with the pre-installed tmap package data (though it is here less obvious that there is empty white space):
rm(list=ls(all=TRUE))
library(tmap)
data("NLD_prov")
map1 <- tm_shape(NLD_prov)+tm_fill()+tm_layout(inner.margins = c(0,0,0,0))
map2 <- tm_shape(NLD_prov)+tm_fill()+tm_layout(inner.margins = c(0,0,0,0))
final_map <-tmap_arrange(map1, map2)
final_map
In the original code I have cropped the input shape file to my desired map extent and also used a bounding box but that does not help:
map_extent<-st_bbox(c(xmin = 8, xmax = 9.1,ymin = 53.8, ymax = 55.1),
crs = st_crs(data))
data_cropped<-crop_shape(data, map_extent, polygon = TRUE)
tm_shape(data_cropped, bbox = map_extent)+
...
How can I force the margins to zero?

Related

Draw a circle on empty canvas in R magick

I want to create an empty (white) canvas at a certain size (1920×1080). On that canvas, I want to place a filled circle at specific coordinates (e.g., 480, 123).
Even going through the vignette (https://docs.ropensci.org/magick/articles/intro.html), I am not able to create such an image.
The answer needs to work in R.
This one works for me
library(magick)
img <- image_blank(width = 1920, height = 1080, color = "none")
drawing <- image_draw(img)
symbols(480, 123, circles = 5, bg = 'black', inches = FALSE, add = TRUE)
dev.off()
# displaying
# print(drawing)
# saving
image_write(drawing, "img.png")

Export leaflet map with fixed zoom and bounding box without padding

I know that I can use mapview::mapshot to export a leaflet map from Rstudio as a PNG. I have not been, however, able to precisely specify the zoom level and region of the map to be exported.
Borrowing some code from this answer to a related question let us consider the following MWE.
library(maps)
library(ggmap)
library(maptools)
library(leaflet)
library(mapview)
library(rgdal)
country <- 'italy';
zoomLevel <- 12;
ita.map <- map( country, fill = TRUE, col = 1, plot = F );
ita.map.ids <- sapply( strsplit( ita.map$names, ':' ), function(x) x[1] );
ita.sp <- map2SpatialPolygons( ita.map, IDs=ita.map.ids, proj4string=CRS("+proj=longlat +datum=WGS84"))
bb<-as.numeric(ita.sp#bbox)
m<-leaflet() %>%
setView(12.48,41.89,zoom=zoomLevel) %>%
addTiles() %>%
addPolygons(data=ita.sp)%>%
addExtent(data=ita.sp)
mapshot(m, file = "italy.png")
results in This is the correct zoom level but clearly does not contain all of Italy.
Adding
%>% fitBounds(bb[1],bb[2],bb[3],bb[4])
to the code above yields which is better, but a) does not respect the specified zoom level, and b) has a lot of unwanted horizontal padding.
I presume that adding width and height arguments to the leaflet() call would help but I am unsure how to automatically obtain the correct values. Also the resulting image would be very large necessitating a reduction in resolution.
How can I export the region of the map containing Italy at a specified zoom level without additional padding?
I dont know that what you want is possible (zoom = 12 and all of italy)...the two things seem mutually exclusive to me... unless you have a enormous figure... as you suggested.
I dont know for certain, but maybe the answer to your padding question is in the vwidth option of webshot. I suppose your figure needs to be taller than wide, so vwidth < vheight...
mapshot(m, file = "italy.png", vwidth = 700, vheight = 744)

R plotly subplot add space between plots

I want to add space between plots but when I play with margin, it either overlaps or cuts.
Here is the code:
library(plotly)
plotList <- function(nplots) {
lapply(seq_len(nplots), function(x) plot_ly())
}
s1 <- subplot(plotList(6), nrows = 2, shareX = TRUE, shareY = TRUE)
s2 <- subplot(plotList(2), shareY = TRUE)
p <- subplot(s1, s2, plot_ly(), nrows = 3, margin = 0.04, heights = c(0.6, 0.3, 0.1))
print(p)
I obtain this:
Whereas i would rather like something like this (image done with paint) with more spacing between the different subplots:
How should I do ?
I was facing the same problem but, fortunately, I found a solution. You can use margin as an argument in Subplot function as follows:
subplot(plot1,
plot2,
nrows = 2,
margin = 0.07)
According to Plotly documentation, you can define only one or four values for each of the margins and those values should be between 0 and 1. If you provide only one value it will be used for all four margins or if you provide four values it will be used in the following order: the first one will be the left margin, the second one will be the right margin, the third one will be the top margin and the last one will be the bottom margin. You can play around and define the values that better fit the layout you want to create.
I found a solution by inserting blank plots between the normal plot. It is however a bit awkward but it works and I've found nothing better
blankplot<-plot_ly()%>%
layout(xaxis=list(visible="FALSE",color="white",tickfont =list(color="white")),
yaxis=list(visible="FALSE",color="white",tickfont =list(color="white")))

spplot/lattice: objects not drawn/overdrawn

I have a grid and I want to produce a map out of this grid with some map elements (scale, north arrow, etc). I have no problem drawing the grid and the coloring I need, but the additional map elements won't show on the map. I tried putting first=TRUE to the sp.layout argument according to the sp manual, but still no success.
I reproduced the issue with the integrated meuse dataset, so you may just copy&paste that code. I use those package versions: lattice_0.20-33 and sp_1.2-0
library(sp)
library(lattice) # required for trellis.par.set():
trellis.par.set(sp.theme()) # sets color ramp to bpy.colors()
alphaChannelSupported = function() {
!is.na(match(names(dev.cur()), c("pdf")))
}
data(meuse)
coordinates(meuse)=~x+y
data(meuse.riv)
library(gstat, pos = match(paste("package", "sp", sep=":"), search()) + 1)
data(meuse.grid)
coordinates(meuse.grid) = ~x+y
gridded(meuse.grid) = TRUE
v.uk = variogram(log(zinc)~sqrt(dist), meuse)
uk.model = fit.variogram(v.uk, vgm(1, "Exp", 300, 1))
meuse[["ff"]] = factor(meuse[["ffreq"]])
meuse.grid[["ff"]] = factor(meuse.grid[["ffreq"]])
zn.uk = krige(log(zinc)~sqrt(dist), meuse, meuse.grid, model = uk.model)
zn.uk[["se"]] = sqrt(zn.uk[["var1.var"]])
meuse.sr = SpatialPolygons(list(Polygons(list(Polygon(meuse.riv)),"meuse.riv")))
rv = list("sp.polygons", meuse.sr, fill = "lightblue")
sampling = list("sp.points", meuse.riv, color = "black")
scale = list("SpatialPolygonsRescale", layout.scale.bar(),
offset = c(180500,329800), scale = 500, fill=c("transparent","black"), which = 4)
text1 = list("sp.text", c(180500,329900), "0", cex = .5, which = 4)
text2 = list("sp.text", c(181000,329900), "500 m", cex = .5, which = 4)
arrow = list("SpatialPolygonsRescale", layout.north.arrow(),
offset = c(181300,329800),
scale = 400, which = 4)
library(RColorBrewer)
library(lattice)
trellis.par.set(sp.theme())
precip.pal <- colorRampPalette(brewer.pal(7, name="Blues"))
spplot(zn.uk, "var1.pred",
sp.layout = list(rv, sampling, scale, text1, text2),
main = "log(zinc); universal kriging standard errors",
col.regions=precip.pal,
contour=TRUE,
col='black',
pretty=TRUE,
scales=list(draw = TRUE),
labels=TRUE)
And that's how it looks...all naked:
So my questions:
Where is the scale bar, north arrow, etc hiding? Did I miss something? Every example I could find on the internet looks similar to that. On my own dataset I can see the scale bar and north arrow being drawn at first, but as soon as the grid is rendered, it superimposes the additional map elements (except for the scale text, that is shown on the map - not the bar and north arrow for some reason I don't seem to comprehend).
The error message appearing on the map just shows when I try to add the sampling locations sampling = list("sp.points", meuse.riv, color = "black"). Without this entry, the map shows without error, but also without additional map elements. How can I show the sampling points on the map (e.g. in circles whose size depends on the absolute value of this sampling point)?
This bothered me for many, many hours by now and I can't find any solution to this. In Bivand et al's textbook (2013) "Applied Spatial Data Analysis with R" I could read the following entry:
The order of items in the sp.layout argument matters; in principle objects
are drawn in the order they appear. By default, when the object of spplot has
points or lines, sp.layout items are drawn before the points to allow grids
and polygons drawn as a background. For grids and polygons, sp.layout
items are drawn afterwards (so the item will not be overdrawn by the grid
and/or polygon). For grids, adding a list element first = TRUE ensures that
the item is drawn before the grid is drawn (e.g. when filled polygons are added). Transparency may help when combining layers; it is available for the
PDF device and several other devices.
Function sp.theme returns a lattice theme that can be useful for plots
made by spplot; use trellis.par.set(sp.theme()) after a device is opened
or changed to make this effective.
However, also with this additional information I wasn't able to solve this problem. Glad for any hint!
The elements you miss are being drawn in panel four, which does not exist, so are not being drawn. Try removing the which = 4.
meuse.riv in your example is a matrix, which causes the error message, but should be a SpatialPoints object, so create sampling by:
sampling = list("sp.points", SpatialPoints(meuse.riv), color = "black")
When working from examples, my advice is to choose examples as close as possible to what you need, and only change one thing at a time.

In R, how to make dots transparent while using scale_size in ggplot2?

This equation leads from my previous question. I want to plot dots that represent total population and so far I used scale_size to make dots' size relative to its total population.
But, I want to make these dots transparent because the dots are covering the map. I am, however, open to other options as long as the message I am trying to send is clear.
# load required packages
library(ggmap)
library(ggplot2)
# query map of Birmingham, AL
al1 <- get_map(location = c(lon = -86.304474, lat = 32.362563), zoom = 11,
source = "osm", maptype = 'terrain')
al1MAP <- ggmap(al1)+ geom_point(data=quote_bmh,
aes(x=IntPtLon, y=IntPtLat, size=TotPop, colour="gold2"),
colour="gold2") + scale_size(range=c(0,15))
To use a uniform transparency, just add alpha = 0.3 to geom_point. alpha can be between 0 and 1, depending on the amount of transparency you want. If you want to make you transparency depend on a variable, just add alpha = var_name to the mapping argument (the aes bit), where var_name is the column name of the variable you want to use for transparency.
Another alternative is to use hollow points, e.g. geom_point(shape = 21). That would make the map directly under the point quite readable while making the edges of the points distinctly visible.
(Unfortunately, my employer blocks the Google API, so I can't post the result)

Resources