Put the name of the district on the plot - r

I am trying to make a plot of the intensity map of Ukraine's regions and intensity depends on the 'value'. Here is my code:
library(sp)
con <- url("http://biogeo.ucdavis.edu/data/gadm2/R/UKR_adm1.RData")
print(load(con))
close(con)
name<-VARNAME_1
gadm$VARNAME_1
value<-c(1:27)
gadm$VARNAME_1<-as.factor(value)
col<- colorRampPalette(c('white', 'black'))(256)
spplot(gadm, "VARNAME_1", main="Ukraine", scales = list(draw = TRUE), col.regions=col)
My question is: Is it possible to put on the plot the names of the regions (I have it as a character vector name in my code to the appropriate place on the map. Or maybe another suggestion to make a map more clear and understandable which region has corresponding value.
Thank you!

one possibility is to do it with colors :
colors=rainbow(length(gadm$NAME_1))
plot(gadm,col=colors)
legend("topleft",legend=gadm$NAME_1,fill=colors,cex=1.3,bty="n" )
or you add names with text :
colors=rainbow(length(gadm$NAME_1))
plot(gadm,col=colors)
text(coordinates(gadm), labels = gadm$NAME_1)

This solution uses plot instead of spplot so we can add labels with text. If you still want to use spplot, check
x11()
col = cm.colors(length(gadm$PID))
plot(gadm, , col=col[rev(gadm$VARNAME_1)])
text(coordinates(gadm), labels = gadm$NAME_1, cex=0.4)
Or if you still want to use spplot, be prepared to do a bit extra. Here's a modification of this answer
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))

Related

Base R Choropleth: colors aren't being applied to the map according to the order of the interval/breaks which makes the map hard to read

I created a choropleth with base R but I'm struggling with the colors. First, the colors don't follow the same order as the intervals and second, two of the intervals are using the same color, all of which makes the graph hard to read. This happens regardless of how many colors I use. It also doesn't matter whether I'm using brewer.pal or base colors.Here is a map with its respective legend illustrating the issue.
Below are the statements that I use to create the graph once data has been downloaded:
#Relevant packages:
library(dplyr)
library(RColorBrewer)
library(rgdal)
#create colors vector
pop_colors <- brewer.pal(8,"Purples")
#create breaks/intervals
pop_breaks <- c(0,20000,40000,60000,80000,100000,120000)
#apply breaks to population
cuts <- cut(cal_pop$Pop2016, pop_breaks, dig.lab = 6)
#create a vector with colors by population according to the interval they belong to:
color_breaks <- pop_colors[findInterval(cal_pop$Pop2016,vec = pop_breaks)]
Create choropleth
plot(cal_pop,col = color_breaks, main = "Calgary Population (2016)")
#create legend
legend("topleft", fill = color_breaks, legend = levels(cuts), title = "Population")
I used readOGR() command to read the shape file, which I'm linking here in case anybody is interested in taking a look at the data.
I'd appreciate any advice you could give me.
Thanks!
Your error is in this line:
color_breaks <- pop_colors[findInterval(cal_pop$Pop2016,vec = pop_breaks)]
I can't read your data file, so I'll use a built-in one from the sf package.
library(sf)
nc <- readOGR(system.file("shapes/", package="maptools"), "sids")
str(nc#data)
colors <- brewer.pal(8,"Purples")
#create breaks/intervals
sid_breaks <- c(0,2,4,6,8,10,12,20,60)
#apply breaks to population
sid_cuts <- cut(nc$SID79, sid_breaks, dig.lab = 6, include=TRUE)
#create a vector with colors by population according to the interval they belong to:
sid_colors <- colors[sid_cuts]
#Create choropleth
par(mar=c(0,0,0,0))
plot(nc, col = sid_colors)
legend("bottomleft", fill = colors, legend = levels(sid_cuts), nc=2, title = "SID (1979)", bty="n")

R get legend with same color as plot lines

Hi I am new to R and am trying to plot multiple files as lines in a scatter plot. I was able to get the plot but not when I try to add legend to the plot. I want the legend with name of the file in the same color as the color of the line made from that file. I tried using the following suggestion from a previous thread -
xlist<-list.files(pattern = NULL)
first=TRUE
cl <- rainbow(22)
for(i in xlist) {
table <- read.table((i),header=T,sep="\t")
table <- table[, 1:2]
if (first) {
plot(table,xlab='Distance from center',ylab='Coverage',ylim=c(0,70),col=1, type="n")
lines(table) #plot and add lines
legend("top", y=NULL, legend = i, col=1)
par(new=T)
first=FALSE
}
else {
lines(table,col=cl[i]) #To add another file to the plot as another line
par(new=F)
plotcol[i] <- cl[i]
legend("top", y=NULL, legend = i, col=plotcol)
}
}
The error is get is - Error in plotcol[i] <- cl[i] : object 'plotcol' not found. Please let me know what I am missing or if there is a better way to plot the lines with different colors and get legend with names of the files with the same color as the lines. Thank you.
I had to make some reproducible examples to get it to work, but the following script works to make the lengends and line colors the same:
#random data
test.df1=data.frame(runif(100)*0.2,runif(100)*0.2)
test.df2=data.frame(runif(100)*0.5,runif(100)*0.5)
test.df3=data.frame(runif(100),runif(100))
test.df4=data.frame(runif(100)*2,runif(100)*2)
test.list=list(test.df1=test.df1,test.df2=test.df2,test.df3=test.df3,test.df4=test.df4) # I used this instead of reading in files from read.table, you shouldn't need this
xlist=c('test.df1','test.df2','test.df3','test.df4') #the list of files
first=TRUE
cl <- rainbow(length(xlist)) #colors dedicated to your list
names(cl)=xlist #this names the vector elements so you can reference them
for(i in xlist) {
i.table <- test.list[[i]]
i.table <- i.table[,c(1:2)]
if (first) {
plot(i.table,xlab='Distance from center',ylab='Coverage',xlim=c(0,2),ylim=c(0,2),col=cl[i], type="n")
lines(i.table,col=cl[i]) #plot and add lines
par(new=T)
first=FALSE
}
else {
lines(i.table,col=cl[i]) #To add another file to the plot as another line
par(new=F)
plotcol <- c(plotcol,cl[i])# pulls colors from the cl vector
}
}
legend("top", y=NULL, legend =xlist, text.col=cl) #label colors should now match
Try ggplot2 package in R. You wouldn't have to code as much too!
https://www.rstudio.com/wp-content/uploads/2015/12/ggplot2-cheatsheet-2.0.pdf

How to color different groups in qqplot?

I'm plotting some Q-Q plots using the qqplot function. It's very convenient to use, except that I want to color the data points based on their IDs. For example:
library(qualityTools)
n=(rnorm(n=500, m=1, sd=1) )
id=c(rep(1,250),rep(2,250))
myData=data.frame(x=n,y=id)
qqPlot(myData$x, "normal",confbounds = FALSE)
So the plot looks like:
I need to color the dots based on their "id" values, for example blue for the ones with id=1, and red for the ones with id=2. I would greatly appreciate your help.
You can try setting col = myData$y. I'm not sure how the qqPlot function works from that package, but if you're not stuck with using that function, you can do this in base R.
Using base R functions, it would look something like this:
# The example data, as generated in the question
n <- rnorm(n=500, m=1, sd=1)
id <- c(rep(1,250), rep(2,250))
myData <- data.frame(x=n,y=id)
# The plot
qqnorm(myData$x, col = myData$y)
qqline(myData$x, lty = 2)
Not sure how helpful the colors will be due to the overplotting in this particular example.
Not used qqPlot before, but it you want to use it, there is a way to achieve what you want. It looks like the function invisibly passes back the data used in the plot. That means we can do something like this:
# Use qqPlot - it generates a graph, but ignore that for now
plotData <- qqPlot(myData$x, "normal",confbounds = FALSE, col = sample(colors(), nrow(myData)))
# Given that you have the data generated, you can create your own plot instead ...
with(plotData, {
plot(x, y, col = ifelse(id == 1, "red", "blue"))
abline(int, slope)
})
Hope that helps.

SpatialLines instead of segments (spplot)

I'd like to use spplot + sp.lines (lattice) instead of plot + segments. Do you know a simple way to realise this, e.g. R: Calculating the shortest distance between two point layers
library(dismo)
require(rgdal)
require(FNN)
laurus <- gbif("Laurus", "nobilis")
locs <- subset(laurus, !is.na(lat) & !is.na(lon),
select = c("country", "lat", "lon"))
locs.uk <- subset(locs, locs$country=="United Kingdom")
locs.ire <- subset(locs, locs$country=="Ireland")
uk_coord <- SpatialPoints(locs.uk[,c("lon","lat")])
ire_coord <- SpatialPoints(locs.ire[,c("lon","lat")])
crs.geo<-CRS("+proj=longlat +ellps=WGS84 +datum=WGS84")
proj4string(uk_coord) <- crs.geo
proj4string(ire_coord) <- crs.geo
uk_coord <- spTransform(uk_coord, CRS("+init=epsg:27700"))
ire_coord <- spTransform(ire_coord, CRS("+init=epsg:27700"))
g = get.knnx(coordinates(uk_coord), coordinates(ire_coord),k=1)
to visualise this
plot(uk_coord, col=2, xlim=c(-1e5,6e5))
plot(ire_coord, add=TRUE)
segments(coordinates(ire_coord)[,1],
coordinates(ire_coord)[,2],
coordinates(uk_coord[g$nn.index[,1]])[,1],
coordinates(uk_coord[g$nn.index[,1]])[,2])
can probably converted to something like
ire <- list("sp.points", ire_coord)
spplot(uk_coord, sp.layout=list(ire))
but is there a easy way to convert segments to SpatialLines i.e. list("sp.lines", Lines(...))
Try panel.segments() from the lattice-package:
library("lattice")
spplot(rbind(uk_coord, ire_coord), auto.key=FALSE,
panel=function(...) {
panel.xyplot(...)
panel.segments(coordinates(ire_coord)[,1],
coordinates(ire_coord)[,2],
coordinates(uk_coord[g$nn.index[,1]])[,1],
coordinates(uk_coord[g$nn.index[,1]])[,2])
})
Understanding panel functions is more powerful than relying on sp.layout in spplot -- and so is using lattice or grid functions directly. The solution with sp.layout could look like this:
spplot(uk_coord, auto.key=FALSE, col.regions = 'black',
sp.layout = list(ire,
list("panel.segments",
coordinates(ire_coord)[,1],
coordinates(ire_coord)[,2],
coordinates(uk_coord[g$nn.index[,1]])[,1],
coordinates(uk_coord[g$nn.index[,1]])[,2])),
xlim = c(-140000,700000))
note that it is not restricted to the sp.lines etc functions; in upcoming sp 1.1-0, quotes around function names can also be omitted.
spplot tries to plot attributes of features in color by default, which is not meaningful here, so what you basically want is an xyplot with controlled aspect ratio (asp="iso").

Equivalent of boxplot lwd parameter for bwplot

I want to have the box plotted with thicker lines. In boxplot function I simply put lwd=2, but in the lattice bwplot I can pull my hair out and haven't found a solution!
(with the box I mean the blue thing in the image above)
Sample code to work with:
require(lattice)
set.seed(123)
n <- 300
type <- sample(c("city", "river", "village"), n, replace = TRUE)
month <- sample(c("may", "june"), n, replace = TRUE)
x <- rnorm(n)
df <- data.frame(x, type, month)
bwplot(x ~ type|month, data = df, panel=function(...) {
panel.abline(h=0, col="green")
panel.bwplot(...)
})
As John Paul pointed out, the line widths are controlled by the the box.rectangle and box.umbrella components of lattice's graphical parameter list. (For your future reference, typing names(trellis.par.get()) is a fast way to scan the list of graphical attributes controlled by that list.)
Here's a slightly cleaner way to set those options for one or more particular figures:
thickBoxSettings <- list(box.rectangle=list(lwd=2), box.umbrella=list(lwd=2))
bwplot(x ~ type|month, data = df,
par.settings = thickBoxSettings,
panel = function(...) {
panel.abline(h=0, col="green")
panel.bwplot(...)
})
One thing you can do is get the trellis settings for the box, and change those. Try
rect.settings<-trellis.par.get("box.rectangle") #gets all rectangle settings
rect.settings$lwd<-4 #sets width to 4, you can choose what you like
trellis.par.set("box.rectangle",rect.settings)
Put these above your bwplot call and it should do it.
The box rectangle settings also has color, fill etc.
Edit to add if you get box.umbrella you can edit it to change what the lines above and below the box look like.
There is a further feature of lattice plots that needs mention. They are really objects, so methods exist for modifying their list representations;
myBW <- bwplot(x ~ type|month, data = df, panel=function(...) {
panel.abline(h=0, col="green")
panel.bwplot(...)
})
newBW <- update(myBW, par.settings=list(box.rectangle=list(lwd=4) ))
plot(newBW) # need to print or plot a grid object
You can also use trellis.focus and apply further updating function to overlay new data or text.

Resources