bivariate raster plots in R - r

I have challenge in plotting a bivariate raster data in one plot with one legend for both variables. my first layer is a continuous variable ranging between -2 and 2 while the second layer is a categorical variable (in years form 1980 to 2011). I need help in ploting the data as one rastr plot with a color scheme and legend which shows both variables as shown here. I appreciate your help.
r <- raster(ncols=100, nrows=100)
r[] <- runif(ncell(r))
crs(r) <- "+proj=lcc +lat_1=48 +lat_2=33 +lon_0=-100 +ellps=WGS84"
r1 <- raster(ncols=100, nrows=100)
r1[] <- 1980:2011
crs(r1) <- "+proj=lcc +lat_1=48 +lat_2=33 +lon_0=-100 +ellps=WGS84"
dta=stack(r,r1)

See ?raster::plot for examples, or do spplot(dta)

I successfully applied the code from the site you mentioned.
kpacks <- c("classInt", 'raster', 'rgdal',
'dismo', 'XML', 'maps', 'sp')
new.packs <- kpacks[!(kpacks %in% installed.packages()[, "Package"])]
if (length(new.packs))
install.packages(new.packs)
lapply(kpacks, require, character.only = T)
remove(kpacks, new.packs)
r <- raster(ncols = 100, nrows = 100)
r[] <- runif(ncell(r))
crs(r) <- "+proj=lcc +lat_1=48 +lat_2=33 +lon_0=-100 +ellps=WGS84"
r1 <- raster(ncols = 100, nrows = 100)
r1[] <- sample(1980:2011, 10000, replace = T)
crs(r1) <- "+proj=lcc +lat_1=48 +lat_2=33 +lon_0=-100 +ellps=WGS84"
dta = stack(r, r1)
plot(dta)
colmat <-
function(nquantiles = 10,
upperleft = rgb(0, 150, 235, maxColorValue = 255),
upperright = rgb(130, 0, 80, maxColorValue = 255),
bottomleft = "grey",
bottomright = rgb(255, 230, 15, maxColorValue = 255),
xlab = "x label",
ylab = "y label") {
my.data <- seq(0, 1, .01)
my.class <- classIntervals(my.data, n = nquantiles, style = "quantile")
my.pal.1 <- findColours(my.class, c(upperleft, bottomleft))
my.pal.2 <- findColours(my.class, c(upperright, bottomright))
col.matrix <- matrix(nrow = 101, ncol = 101, NA)
for (i in 1:101) {
my.col <- c(paste(my.pal.1[i]), paste(my.pal.2[i]))
col.matrix[102 - i, ] <- findColours(my.class, my.col)
}
plot(
c(1, 1),
pch = 19,
col = my.pal.1,
cex = 0.5,
xlim = c(0, 1),
ylim = c(0, 1),
frame.plot = F,
xlab = xlab,
ylab = ylab,
cex.lab = 1.3
)
for (i in 1:101) {
col.temp <- col.matrix[i - 1, ]
points(
my.data,
rep((i - 1) / 100, 101),
pch = 15,
col = col.temp,
cex = 1
)
}
seqs <- seq(0, 100, (100 / nquantiles))
seqs[1] <- 1
col.matrix <- col.matrix[c(seqs), c(seqs)]
}
col.matrix <-
colmat(
nquantiles = 10,
upperleft = "blue",
upperright = "yellow",
bottomleft = "green",
bottomright = "red",
xlab = "My x label",
ylab = "My y label"
)
bivariate.map <-
function(rasterx,
rastery,
colormatrix = col.matrix,
nquantiles = 10) {
quanmean <- getValues(rasterx)
temp <- data.frame(quanmean, quantile = rep(NA, length(quanmean)))
brks <-
with(temp, quantile(temp, na.rm = TRUE, probs = c(seq(0, 1, 1 / nquantiles))))
r1 <-
within(
temp,
quantile <-
cut(
quanmean,
breaks = brks,
labels = 2:length(brks),
include.lowest = TRUE
)
)
quantr <- data.frame(r1[, 2])
quanvar <- getValues(rastery)
temp <- data.frame(quanvar, quantile = rep(NA, length(quanvar)))
brks <-
with(temp, quantile(temp, na.rm = TRUE, probs = c(seq(0, 1, 1 / nquantiles))))
r2 <-
within(temp,
quantile <-
cut(
quanvar,
breaks = brks,
labels = 2:length(brks),
include.lowest = TRUE
))
quantr2 <- data.frame(r2[, 2])
as.numeric.factor <- function(x) {
as.numeric(levels(x))[x]
}
col.matrix2 <- colormatrix
cn <- unique(colormatrix)
for (i in 1:length(col.matrix2)) {
ifelse(is.na(col.matrix2[i]),
col.matrix2[i] <- 1,
col.matrix2[i] <- which(col.matrix2[i] == cn)[1])
}
cols <- numeric(length(quantr[, 1]))
for (i in 1:length(quantr[, 1])) {
a <- as.numeric.factor(quantr[i, 1])
b <- as.numeric.factor(quantr2[i, 1])
cols[i] <- as.numeric(col.matrix2[b, a])
}
r <- rasterx
r[1:length(r)] <- cols
return(r)
}
my.colors = colorRampPalette(c("white", "lightblue", "yellow", "orangered", "red"))
plot(
r,
frame.plot = F,
axes = F,
box = F,
add = F,
legend.width = 1,
legend.shrink = 1,
col = my.colors(255)
)
map(interior = T, add = T)
bivmap <- bivariate.map(r, r1, colormatrix = col.matrix, nquantiles = 10)
# Plot the bivariate map:
plot(
bivmap,
frame.plot = F,
axes = F,
box = F,
add = F,
legend = F,
col = as.vector(col.matrix)
)
col.matrix

Related

Drawing a partially transparent density polygon

How can I make this red polygon partially transparent so I can see the points underneath it?
library(ks)
set.seed(1234)
x <- runif(1000) + -150
y <- runif(1000) + 20
my.data <- data.frame(x,y)
my.matrix <- as.matrix(my.data)
my_gps_hpi <- Hpi(x = my.matrix, pilot = "samse", pre = "scale")
my.fhat <- kde(x = my.matrix, compute.cont = TRUE, h = my_gps_hpi,
xmin = c(min(my.data$x), min(my.data$y)),
xmax = c(max(my.data$x), max(my.data$y)),
bgridsize = c(100, 100))
my.contours <- c(75)
contourLevels(my.fhat, cont = my.contours)
contourSizes(my.fhat, cont = my.contours, approx = TRUE)
plot(my.data$x, my.data$y)
plot(my.fhat, lwd = 3, display = "filled.contour", cont = my.contours, add = TRUE)
png(file="transparent_polygon_June21_2021.png")
plot(my.data$x, my.data$y)
plot(my.fhat, lwd = 3, display = "filled.contour", cont = my.contours, add = TRUE)
dev.off()
I think I have figured out a solution by digging around in the source code in the file kde.R.
I made several changes to my code.
Changed my.fhat to fhat because the source code might want fhat.
Changed my.contours to contours for the same reason.
Changed contourLevels(my.fhat, cont = my.contours) to hts <- contourLevels(fhat, cont = contours) for the same reason.
Extracted the col.fun from the source code and changed it to return the color of my choice: col.fun <- function(n) {rgb(255, 0, 0, 127, maxColorValue=255)}.
Modified the plot statement to that shown in the code below.
Here is the modified R code:
setwd('C:/Users/mark_/Documents/ctmm/density_in_R/')
set.seed(1234)
library(ks)
x <- runif(1000) + -150
y <- runif(1000) + 20
my.data <- data.frame(x,y)
my.matrix <- as.matrix(my.data)
gps_hpi <- Hpi(x = my.matrix, pilot = "samse", pre = "scale")
fhat <- kde(x = my.matrix, compute.cont = TRUE, h = gps_hpi,
xmin = c(min(my.data$x), min(my.data$y)),
xmax = c(max(my.data$x), max(my.data$y)),
bgridsize = c(100, 100))
contours <- c(75)
hts <- contourLevels(fhat, cont = contours)
contourSizes(fhat, cont = contours, approx = TRUE)
col.fun <- function(n) {rgb(255, 0, 0, 127, maxColorValue=255)}
col.fun(1)
plot(fhat, lwd = 3, display = "filled.contour", cont = contours, col.fun = col.fun(1), drawpoints=TRUE)
png(file="transparent_polygon_June22_2021.png")
plot(fhat, lwd = 3, display = "filled.contour", cont = contours, col.fun = col.fun(1), drawpoints=TRUE)
dev.off()

Dot Plot include vertical line and dots of different colors

I needed to include in the code below, a vertical line,
for example, in position x = 5 and that all points smaller than 5 have another color,
for example blue.
The values of a variable can be read from the x-axis, and the y-axis shows the order of the observations in the variable (from bottom to top). Isolated points as the far ends, and on either side in a plot, suggest potentional outliers
Thanks
library(dplyr)
library(lattice)
n = 1000
df <- tibble(
xx1 = runif(n, min = 3, max = 10),
xx2 = runif(n, min = 3, max = 10),
xx3 = runif(n, min = 3, max = 10)
)
MyVar <- c("xx1","xx2","xx3")
MydotplotBR <- function(DataSelected){
P <- dotplot(as.matrix(as.matrix(DataSelected)),
groups=FALSE,
strip = strip.custom(bg = 'white',
par.strip.text = list(cex = 1.2)),
scales = list(x = list(relation = "same",tck = 1,
draw = TRUE, at=seq(0,10,1)),x=list(at=seq),
y = list(relation = "free", draw = FALSE),
auto.key = list(x =1)),
col=10,
axes = FALSE,
cex = 0.4, pch = 5,
xlim=c(0,10),
xlab = list(label = "Variable Value", cex = 1.5),
ylab = list(label = "Order of data in the file", cex = 1.5))
print(P)
}
(tempoi <- Sys.time())
Vertemp <- MydotplotBR(df[,MyVar])
(tempof <- Sys.time()-tempoi)
I find it weird that you want a color dependent only on the x-axis when values are also used on the y-axis of other plots.
Nevertheless, here's a homemade pairs_cutoff() function doing what you want.
pairs_cutoff <- function(data, cutoff, cols = c("red", "blue"),
only.lower = F, ...){
data <- as.data.frame(data)
cns <- colnames(data)
nc <- ncol(data)
layout(matrix(seq_len(nc^2), ncol = nc))
invisible(
sapply(seq_len(nc), function(i){
sapply(seq_len(nc), function(j){
if(i == j){
plot.new()
legend("center", bty = "n", title = cns[i], cex = 1.5, text.font = 2, legend = "")
} else {
if(j < i & only.lower)
plot.new()
else{
if(is.null(cutoff))
cols <- cols[1]
plot(data[,i], data[,j], col = cols[(data[,i] < cutoff) + 1],
xlab = cns[i], ylab = cns[j], ...)
}
}
})
})
)
}
Using your suggested data :
n = 1000
dat <- tibble(
xx1 = runif(n, min = 3, max = 10),
xx2 = runif(n, min = 3, max = 10),
xx3 = runif(n, min = 3, max = 10)
)
pairs_cutoff(dat, cutoff = 5, only.lower = T)
outputs the following plot :
You can specify extra parameters to the plot function (eg. pch) directly to pairs_cutoff.
Also, if you want the full symmetric grid of plots, set only.lower = F.

Fanplot in R with other package than fanplot

I generally create a fanplot like this:
n.ahead <- 10
m <- matrix(,nrow = 5000,ncol = 10)
library(fanplot)
m[,1] <- rnorm(5000,0.01,sd = 0.005)
m[,2] <- rnorm(5000,0.02,0.006)
m[,3] <- rnorm(5000,0.03,0.008)
m[,4] <- rnorm(5000,0.04,0.01)
m[,5] <- rnorm(5000,0.06,0.013)
m[,6] <- rnorm(5000,0.1,0.015)
m[,7] <- rnorm(5000,0.11,0.02)
m[,8] <- rnorm(5000,0.13,0.025)
m[,9] <- rnorm(5000,0.14,0.05)
m[,10] <- rnorm(5000,0.18,0.07)
n.ahead <- 10
fancol <- colorRampPalette(c('black', 'white'))
plot(
NULL, type = 'n', lwd = 3, col = 'black',
xlim = c(0, n.ahead), ylab = 'Y', ylim = c(0,max(m)), xlab = 'Year',
las = 1, xaxt = 'n', main = 'Y'
)
fan(
m, fan.col = fancol, ln.col = 'grey', txt = c('90','95', '99'),
anchor = 0, frequency = 1, probs = c(seq(1, 99, 1), 99.9, 99.95, 99.99), ln =
c(50, 90, 99, 99.9, 99.95, 99.99)
)
axis(1, at = 0:n.ahead, tcl = 0.5)
axis(1, at = seq(0, n.ahead, 0.25), labels = FALSE, tcl = 0.25)
It does the trick in the sense that a fanlplot is created. However, I don't really like it. Are there alternatives with dynamic charts like we see in dygraphs and rCharts I can use in Shiny?
Thanks.

define breaks for hist2d in R

is there a simple way to define breaks instead of nbins for a 2d histogram (hist2d) in R?
I want to define the range for the x- and yaxis for a 2D histogram and the number of bins for each dimension.
My example:
# example data
x <- sample(-1:100, 2000, replace=T)
y <- sample(0:89, 2000, replace=T)
# create 2d histogram
h2 <- hist2d(x,y,nbins=c(23,19),xlim=c(-1,110), ylim=c(0,95),xlab='x',ylab='y',main='hist2d')
This results in this 2D histogram output 1
----------------------------
2-D Histogram Object
----------------------------
Call: hist2d(x = x, y = y, nbins = c(23, 19), xlab = "x", ylab = "y",
xlim = c(-1, 110), ylim = c(0, 95), main = "hist2d")
Number of data points: 2000
Number of grid bins: 23 x 19
X range: ( -1 , 100 )
Y range: ( 0 , 89 )
I need
X range: ( -1 , 110 )
Y range: ( 0 , 95 )
instead.
My attempt to define the xlim and ylim only extends the plot but does not define the axis range for the histogram. I know that there would be no data in the additional bins.
Is there a way to define
xbreaks = seq(-1,110,5)
ybreaks = seq(0,95,5)
instead of using nbins which divides the range from minimum to maximum into the given number of bins?
Thank you for your help
I changed the code a little bit and this version should work the with explicitly defining the breaks for both axes. First you have to load the function. Then you can give the x.breaks and y.breaks options with x.breaks=seq(0,10,0.1).
If same.scale is true, you only need x.breaks
The return value addionaly contains the number of bins and the relative counts.
Also, you can include a legend if wanted, by setting legend=TRUE. For that you need to have the package Fields
hist2d_breaks = function (x, y = NULL, nbins = 200,same.scale = FALSE, na.rm = TRUE,
show = TRUE, col = c("black", heat.colors(12)), FUN = base::length,
xlab, ylab,x.breaks,y.breaks, ...)
{
if (is.null(y)) {
if (ncol(x) != 2)
stop("If y is ommitted, x must be a 2 column matirx")
y <- x[, 2]
x <- x[, 1]
}
if (length(nbins) == 1)
nbins <- rep(nbins, 2)
nas <- is.na(x) | is.na(y)
if (na.rm) {
x <- x[!nas]
y <- y[!nas]
}
else stop("missinig values not permitted if na.rm=FALSE")
if(same.scale){
x.cuts = x.breaks;
y.cuts = x.breaks;
}else{
x.cuts <- x.breaks
y.cuts <- y.breaks
}
index.x <- cut(x, x.cuts, include.lowest = TRUE)
index.y <- cut(y, y.cuts, include.lowest = TRUE)
m <- tapply(x, list(index.x, index.y), FUN)
if (identical(FUN, base::length))
m[is.na(m)] <- 0
if (missing(xlab))
xlab <- deparse(substitute(xlab))
if (missing(ylab))
ylab <- deparse(substitute(ylab))
if (show){
if(legend){
image.plot(x.cuts, y.cuts, m, col = col, xlab = xlab, ylab = ylab,
...)
}else{
image(x.cuts, y.cuts, m, col = col, xlab = xlab, ylab = ylab,
...)
}
}
midpoints <- function(x) (x[-1] + x[-length(x)])/2
retval <- list()
retval$counts <- m
retval$counts_rel <- m/max(m)
retval$x.breaks = x.cuts
retval$y.breaks = y.cuts
retval$x = midpoints(x.cuts)
retval$y = midpoints(y.cuts)
retval$nobs = length(x)
retval$bins = c(length(x.cuts),length(y.cuts))
retval$call <- match.call()
class(retval) <- "hist2d"
retval
}
The call of (my data) then brings the following:
hist2d_breaks(df,x.breaks=seq(0,10,1),y.breaks=seq(-10,10,1),legend=TRUE)
brings up the following plot
2D Histogram with breaks
Revise the "hist2d" as follows
hist2d_range<-function (x, y = NULL, nbins = 200, same.scale = TRUE, na.rm = TRUE,
show = TRUE, col = c("black", heat.colors(12)), FUN = base::length,
xlab, ylab,range=NULL, ...)
{
if (is.null(y)) {
if (ncol(x) != 2)
stop("If y is ommitted, x must be a 2 column matirx")
y <- x[, 2]
x <- x[, 1]
}
if (length(nbins) == 1)
nbins <- rep(nbins, 2)
nas <- is.na(x) | is.na(y)
if (na.rm) {
x <- x[!nas]
y <- y[!nas]
}
else stop("missinig values not permitted if na.rm=FALSE")
if (same.scale) {
if(is.null(range))
{
x.cuts <- seq(from = min(x, y), to = max(x, y), length = nbins[1] +
1)
y.cuts <- seq(from = min(x, y), to = max(x, y), length = nbins[2] +
1)
}else{
x.cuts <- seq(from = range[1], to = range[2], length = nbins[1] + 1)
y.cuts <- seq(from = range[1], to = range[2], length = nbins[1] + 1)
}
}
else {
x.cuts <- seq(from = min(x), to = max(x), length = nbins[1] +
1)
y.cuts <- seq(from = min(y), to = max(y), length = nbins[2] +
1)
}
index.x <- cut(x, x.cuts, include.lowest = TRUE)
index.y <- cut(y, y.cuts, include.lowest = TRUE)
m <- tapply(x, list(index.x, index.y), FUN)
if (identical(FUN, base::length))
m[is.na(m)] <- 0
if (missing(xlab))
xlab <- deparse(substitute(xlab))
if (missing(ylab))
ylab <- deparse(substitute(ylab))
if (show)
image(x.cuts, y.cuts, m, col = col, xlab = xlab, ylab = ylab,
...)
midpoints <- function(x) (x[-1] + x[-length(x)])/2
retval <- list()
retval$counts <- m
retval$x.breaks = x.cuts
retval$y.breaks = y.cuts
retval$x = midpoints(x.cuts)
retval$y = midpoints(y.cuts)
retval$nobs = length(x)
retval$call <- match.call()
class(retval) <- "hist2d"
retval
}
This function has an additional argument "range".
The revised point is as follows.
if(is.null(range))
{
x.cuts <- seq(from = min(x, y), to = max(x, y), length = nbins[1] +
1)
y.cuts <- seq(from = min(x, y), to = max(x, y), length = nbins[2] +
1)
}else{
x.cuts <- seq(from = range[1], to = range[2], length = nbins[1] + 1)
y.cuts <- seq(from = range[1], to = range[2], length = nbins[1] + 1)
}

Correlation Corrgram Configuration

I built a correlation matrix with the corrgram package and I done some configuration. I would like to use the spearman correlation method. Is it possible with this code?
panel.shadeNtext <- function (x, y, corr = NULL, col.regions, ...)
{
corr <- cor(x, y, use = "pair")
results <- cor.test(x, y, alternative = "two.sided")
est <- results$p.value
stars <- ifelse(est < 0.001, "***",
ifelse(est < 0.01, "**",
ifelse(est < 0.05, "*", "")))
ncol <- 14
pal <- col.regions(ncol)
col.ind <- as.numeric(cut(corr, breaks = seq(from = -1, to = 1,
length = ncol + 1), include.lowest = TRUE))
usr <- par("usr")
rect(usr[1], usr[3], usr[2], usr[4], col = pal[col.ind],
border = NA)
box(col = "lightgray")
on.exit(par(usr))
par(usr = c(0, 1, 0, 1))
r <- formatC(corr, digits = 2, format = "f")
cex.cor <- .4/strwidth("-X.xx")
fonts <- ifelse(stars != "", 2,1)
text(0.5, 0.5, paste0(r,"\n", stars), cex = cex.cor)
}
# Generate some sample data
sample.data <- matrix(rnorm(100), ncol=10)
# Call the corrgram function with the new panel functions
corrgram(sample.data, type="data", lower.panel=panel.shadeNtext,
upper.panel=NULL,cor.method="spearman")

Resources