R tmap tm_facet assigns values to the wrong location - r

I'm trying to use tm_facets to display data (in this case on maize yields) in 2005, 2050, and 2080. The test.RDS file is available here.
library(tmap)
map.temp <- readRDS("test.RDS")
title <- "Maize rainfed yield <br> (mt/ha)"
legend_title <- "(mt/ha)"
breaks <- c(1.0, 2139.2, 4277.5, 6415.8, 8554)
tm_shape(map.temp) +
tm_polygons(col = "value", title = legend_title) +
tm_facets(by = "year") +
tm_layout(main.title = title) +
tm_view(view.legend.position = c("left", "bottom"))
The code above does this, but displays the data in the wrong polygon and wrong years. To see this, run the script and click the dark red area in northeast Canada. The popup in all three maps says AMR_RUS with value of 5,634, but the colors are different. View the map.temp file (I'm using Rstudio to do all of this). Filter on FPU with AMR_RUS. The 2005 value is 6,047, 2050 is 5634 and 2080 is 4406 (climate change will reduce yields in this area). Next look at the first couple of entries in the geometry column. The lat long coordinates are for a region along the Chinese-Russian border. The Amur River makes up that border and AMR_RUS FPU (food production unit) is to the north of the Amur River in Russia.
Is the problem with my code or data or the tm_facet function in tmap?

Unfortunately, I can't figure out a solution with tmap, and not sure why is doing that misplacing of polygon names and values in the popup. UPDATE: seems that this was a tmap bug, which was immediately fixed - see tmap issue 268.
I know you asked for tmap solution, but, alternatively, could be worth exploring a solution with mapview - check this out and see if it works for you:
library(mapview)
breaks <- c(1.0, 2139.2, 4277.5, 6415.8, 8554)
m_2005 <- mapview(map.temp[map.temp$year == 2005, ],
zcol = "value",
at = breaks,
layer.name = "2005 - mt/ha")
m_2050 <- mapview(map.temp[map.temp$year == 2050, ],
zcol = "value",
at = breaks,
layer.name = "2050 - mt/ha")
m_2080 <- mapview(map.temp[map.temp$year == 2080, ],
zcol = "value",
at = breaks,
layer.name = "2080 - mt/ha")
sync(m_2005, m_2050, m_2080) # add ncol = 1, if you wish 1 column representation

Related

Plotting a raster layer by setting a specific color to a non-central value

I have been trying to plot a raster layer by setting the value 1 to the color white. I looked at many examples but still couldn't construct the colors as I wish. I want contrasting colors for the values below and above 1. I would like them start with a light tone and get darker as they go further from 1. I also posted the figure that I managed to create so far. It looks a bit weird since it is based on made up data. I can't share the real data unfortunately. The best would be to create this using viridis colors, but I don't know how doable it is.
I wonder if anyone has any suggestions?
I got the idea of breakpoints and colors from the following post :https://gis.stackexchange.com/questions/17339/raster-legend-in-r-how-to-colour-specific-values .
I got the shapefile from here : https://gadm.org/download_country.html .
Here is my example:
library(rgdal)
library(raster)
library(sp)
library(sf)
set.seed(123)
proj = "+units=km +proj=utm +zone=37 +ellps=clrk80 +towgs84=-160,-6,-302,0,0,0,0 +no_defs"
map0 = readOGR(dsn = "dataFiles/gadm40_NGA_shp", #https://gadm.org/download_country.html (Nigeria/shapefile)
layer = "gadm40_NGA_0")
map0_trnsfrmd = spTransform(map0,proj)
predRaster <- raster(ncol=400, nrow=400, xmn=-3805.7869, xmx=-2222.120, ymn=562.5405, ymx=1828.165)
res(predRaster) = 5
projection(predRaster) = "+units=km +proj=utm +zone=37 +ellps=clrk80 +towgs84=-160,-6,-302,0,0,0,0 +no_defs"
idx = 1:80201 # index for the cell numbers
val = c(rnorm(50000), rep(1,10201),runif(20000,min=0, max=3))
r = setValues(predRaster, values = val, index=idx) # assign values to the cells
r = raster::mask(crop(r, extent(map0_trnsfrmd)), map0_trnsfrmd, snap = 'out')
below=val[val<1]
above=val[val>1]
min(below)
[1] -4.289319
max(above)
[1] 4.438207
max(below)
[1] 0.9998253
min(above)
[1] 1.000105
breakpoints = c(-4.289319, 0.9998253, 1.000105, 4.438207)
colors = c("red","white","blue")
par(mgp=c(4,1,0), mar=c(5,7,3,1)+0.1)
plot(r,las=1, asp = 1, xlab="Easting", ylab="Northing", axis.args = list(cex.axis=1),
legend.shrink =1,legend.width=2, cex.lab=2, cex.axis=1.5, legend.args = list("title", cex =1),breaks=breakpoints,col=colors)
exampleplot
Please look below on the colors definition. I have removed the shape for clarity.
library(rgdal)
library(raster)
library(sp)
library(sf)
set.seed(123)
predRaster <- raster(ncol=400, nrow=400, xmn=-3805.7869, xmx=-2222.120, ymn=562.5405, ymx=1828.165)
res(predRaster) = 5
projection(predRaster) = "+units=km +proj=utm +zone=37 +ellps=clrk80 +towgs84=-160,-6,-302,0,0,0,0 +no_defs"
idx = 1:80201 # index for the cell numbers
val = c(rnorm(50000), rep(1,10201),runif(20000,min=0, max=3))
r = setValues(predRaster, values = val, index=idx) # assign values to the cells
below=val[val<1]
above=val[val>1]
colors = c(colorRampPalette(c(rgb(1,0,0,1), rgb(1,0,0,0.1)), alpha = TRUE)(19),"white", colorRampPalette(c(rgb(0,0,1,0.1), rgb(0,0,1,1)), alpha = TRUE)(19))
plot(r, col=colors, xlab="Easting", ylab="Northing", axis.args = list(cex.axis=1),
legend.shrink =1,legend.width=2, cex.axis=1.5, legend.args = list("title", cex =1))
You can increase the number of colors on both sides. Please check the help for colorRampPalette() function.
Created on 2022-08-31 by the reprex package (v2.0.1)

tmap - changing the behaviour of tm_markers

Here is a reproducible example
#load the packages
library(easypackages)
packages("tidyverse","readxl","sf","tmaptools","tmap","lubridate",
"lwgeom","Cairo","nngeo","purrr","scales", "ggthemes","janitor")
polls<-st_as_sf(read.csv(url("https://www.caerphilly.gov.uk/CaerphillyDocs/FOI/Datasets_polling_stations_csv.aspx")),
coords = c("Easting","Northing"),crs = 27700)%>%
mutate(date = sample(seq(as.Date('2020/01/01'), as.Date('2020/05/31'), by="day"), 147))
test_stack<-polls%>%st_join(polls%>%st_buffer(dist=1000),join=st_within)%>%
filter(Ballot.Box.Polling.Station.x!=Ballot.Box.Polling.Station.y)%>%
add_count(Ballot.Box.Polling.Station.x)%>%
rename(number_of_neighbours = n)%>%
mutate(interval_date = date.x-date.y)%>%
subset(select = -c(6:8,10,11,13:18))## removing this comment will summarise the data so that only number of neighbours is returned %>%
distinct(Ballot.Box.Polling.Station.x,number_of_neighbours,date.x)%>%
filter(number_of_neighbours >=2)
polls%>%mutate(id = as.numeric(row_number()))%>% mutate(thing = case_when(id %% 2 == 0 ~ "stuff",
id %% 2 !=0 ~ "type"))->polls
qtm(polls)
tmap_mode("view")
tm_shape(polls) + tm_markers(col = "thing")
tm_shape(polls) + tm_dots(col ="thing", size = 0.75)
what I'd like to do is change the colour and size of tm_markers, because in the thing I want to use it in it would be nice to make use of different colour markers easily.
Linked to this, is understanding how the clustering of markers works when the map mode is "view" and an html is generated.
Any help on tm_marker behaviour and tm_marker clustering would be brilliant.
thanks == "MANY!"
In the end it turns out to be much simpler than using markers. I don't like "markers", aesthetically, but I do like "dots" and tm_dots lets you sort out the colours more easily (or in my head it's easier..) . And the thing is. Well. Clustering can be applied to dots, bubbles, and tm_symbols.
It's all in here:
https://cran.r-project.org/web/packages/tmap/tmap.pdf
(p 89/90)
ANYWAY
tm_shape(polls) + tm_dots(col ="thing", size = 0.75,clustering = T)
that's the answer (for me). I can cluster and then colour by a field.

Basemap Lambert Azimuthal Equal Area Plot: strange artefact

I am trying to use the following code to plot gridded data in the Pacific hemisphere; however, there seems to be a weird artifact as the code below demonstrates. I was wondering if someone would be kind enough to show where I'm going wrong with the setup. Thank you.
LON_0 = -160
LAT_0 = 20
plt.close()
fig = plt.figure(figsize=(11.6,11.6))
ax = plt.subplot()
lats = np.linspace(90,-90,181)
lons = np.linspace(180,-180,361)
lons, lats = np.meshgrid(lons,lats)
m = Basemap(width=18000000, height=18000000,
lat_ts=LAT_0, lat_0=LAT_0, lon_0=LON_0,
ax=ax, projection='laea',
resolution='c')
m.drawcoastlines()
data =np.sin(lons*5*math.pi/180.)**2+np.sin(lats*5*math.pi/180.)**2
shiftedLons,shiftedData = m.shiftdata(lons, data,
lon_0=LON_0)
px,py = m(shiftedLons, lats)
cbinfo = m.pcolormesh(px, py, shiftedData, cmap='rainbow')
output

R spplot diagrams on the map

Hallo everyone can anybody help me to upgrade my code with possibility of insering additional data into my map. This is the code that draw me a map with intensity of migration, and I am trying to add ehtnic information of every region (many small pie charts).
to draw a map
con <- url("http://biogeo.ucdavis.edu/data/gadm2/R/UKR_adm1.RData")
print(load(con))
close(con)
name<-gadm$VARNAME_1
value<-c(4,2,5,2,1,2,4,2,2,4,1,1,1,4,3,3,1,1,3,1,2,4,5,3,4,2,1)
gadm$VARNAME_1<-as.factor(value)
col<- colorRampPalette(c('cadetblue4','cadetblue1','mediumseagreen','tan2','tomato3'))(260)
spplot(gadm, "VARNAME_1", main="Ukraine", scales = list(draw = TRUE), col.regions=col)
sp.label <- function(x, label) {
list("sp.text", coordinates(x), label)
}
NAME.sp.label <- function(x) {
sp.label(x, x$NAME_1)
}
draw.sp.label <- function(x) {
do.call("list", NAME.sp.label(x))
}
spplot(gadm, 'VARNAME_1', sp.layout = draw.sp.label(gadm), col.regions=col,
colorkey = list(labels = list( labels = c("Very low","Low", "Average",
"High","Very high"),
width = 1, cex = 1)))
and this is a part of df, that I am trying to add to that map as pie charts or bar charts, with every latitude (lat) and longitude (long) to locate mu bar or pie charts.
df<-data.frame(region=c('Kiev oblast', 'Donezk oblast'),
rus=c(45,35), ukr=c(65,76), mold=c(11,44),long=c(50.43,48),
lat=c(30.52, 37.82))
i found one example and another but... can't figure out how to use it in ma case.
Hope for your help, thank you.
only that solution i have discovered by now, but it doesn't upgrade my code(((
mapPies( df,nameX="lat", nameY="long", nameZs=c('rus','ukr','mold'),
xlim=c(30,33), ylim=c(44,53), symbolSize = 2)
perhaps this will help:
pieSP The function provide SpatialPolygonsDataFrame depending on few attributes, ready to use for plotGoogleMaps or spplot.
library(plotGoogleMaps)
data(meuse)
coordinates(meuse)<-~x+y
proj4string(meuse) <- CRS('+init=epsg:28992')
pies <- pieSP(meuse,zcol=c('zinc','lead','copper'), max.radius=120)
pies$pie <- rep(c('zinc','lead','copper'),155)
pies$pie2 <- rep(1:3,155)
spplot(pies, 'pie2')

map with wrong colors but right assigned on legend?

I've been mapping a choropleth map and when I compare the colours drawn to the numbers they re assigned to it doesn't fit.
so here is my data
zip latitude longitude count2.x count2.freq reg colorBuckets colma
99501 61.21680 -149.87828 AK 67 Alaska 1 #EDF8FB
35010 32.90343 -85.92669 AL 1582 Alabama 3 #99D8C9
90001 33.97291 -118.24878 CA 20970 California 6 #006D2C
20001 38.90771 -77.01732 DC 952 NA 2 #CCECE6
so the code from the beginning that I've been using is the following
library("zipcode")
library("maps")
library("plyr")
library("RColorBrewer")
colors=brewer.pal(6, "BuGn")
data(zipcode)
merge1<-merge(zipcode, tel2, by.x='zip', by.y='zip_code', all.y=TRUE)
result<- ddply(merge1, .(state), transform, count2 = count(state))
#remove NA's#
final<- result[complete.cases(result),]
#remove duplicates#
nodupl <- final[!duplicated(final$state),]
#add state to abbreviations#
nodupl$reg<-state.name[match(nodupl$count2.x, state.abb)]
#intervalle bestimmen#
nodupl$colorBuckets<- as.numeric(cut(nodupl$count2.freq, c(0,500,1000,5000,10000,15000,22000)))
#intervall legend#
text<- c("< 500", "500 - 999", "1000 - 4999","5000 - 9999", "10000 - 14999", "15000 - 22000")
#see what color is assign to where#
nodupl$colma<- colors[nodupl$colorBuckets]
map("state",regions=nodupl$reg, exact=FALSE, col = colors[nodupl$colorBuckets], fill = TRUE,resolution = 0,lty = 0)
map("state",col = "black",fill=FALSE,add=TRUE,lty=1,lwd=1)
#legend plotten#
par(xpd=TRUE)
legend("bottomleft", text, horiz=FALSE, fill=colors)
so the problem is again if I see the legend the colours are assigned right but if I double check the numbers in my column (row count2.freq) with the colours on the map they don't fit. e.g california is really light colored but it should be dark. does anyone see what has been done wrong. plus I have some trouble with positioning the legend the way I have it is right on the map so Idon't see the map anymore. what could I do about that?
thanks for your help even though its saturday
The region Alaska is not available in the map function. Hence, your map shows the second and third entry of nodupl$reg (i.e., Alabama and California). But the first and second of your colours are used.
To print these states in the desired colours, use the command
map("state", regions=nodupl$reg[2:3], exact=FALSE,
col = colors[nodupl$colorBuckets][2:3], fill = TRUE,resolution = 0,lty = 0)
But I recommend searching a map of Alaska too.

Resources