R: change order of layers in rasterstack - r

I have two sets of rasterstacks (each with a few hundred raster layers) - the first is a rasterstack containing a set of sensored time series images (with gap) and a second stack of temporally interpolated images for the gaps of the first set. Naming of the layers in each set is according to the day they where measured/or interpolated, starting from day 1....n
I now want to combine these two sets into one ordered (from 1 to n according to layer name) rasterstack. I have looked into different ways of doing this but haven't been able to get the results;
A way to order the layers within a rasterstack (for example by using something like this (comb_r is the raster stack from my reproducible example below). This reorders the names but not the entire layers:
names(comb_r)<-comb_r[order(names(comb_r))]
create two lists of layers in both stacks using the unstack function and than create a combined ordered list as an input to a new stack operation (did not get this to work).
finally I guess I could save all layers onto the hard disk and than reassemble a stack from there (considering the many layers probably not the best way forward).
Any suggestions on how to proceed would be welcome. I have added a toy example of my problem here:
library(raster)
r1 <- raster(matrix(runif(9), ncol = 3))
r2 <- raster(matrix(runif(9), ncol = 3))
r3 <- raster(matrix(runif(9), ncol = 3))
r4 <- raster(matrix(runif(9), ncol = 3))
r5 <- raster(matrix(runif(9), ncol = 3))
r <- stack(r1, r2, r3,r4,r5)
names(r)<-c(1,4,6,8,10)
r6 <- raster(matrix(runif(9), ncol = 3))
r7 <- raster(matrix(runif(9), ncol = 3))
r8 <- raster(matrix(runif(9), ncol = 3))
r9 <- raster(matrix(runif(9), ncol = 3))
r10 <- raster(matrix(runif(9), ncol = 3))
rr <- stack(r6,r7,r8,r9,r10)
names(rr)<-c(2,3,5,7,9)
comb_r<-stack(r,rr)

Can you not just take a 'subset' in a different order:
subset(comb_r, order(c(1,4,6,8,10,2,3,5,7,9)))
You can choose the second argument of 'subset' to reflect your desired ordering - the one you've given is slightly odd, in that it takes one from r, then two from rr, then alternates from r and rr.

Calling order within the subset function did not work for me.
I used the following:
subset(comb_r, c(1,4,6,8,10,2,3,5,7,9))

This should works:
ReorderStack<- stack(comb_r[[1]],comb_r[[4]],comb_r[[6]],comb_r[[8]],comb_r[[10]],
comb_r[[2]], comb_r[[3]],comb_r[[5]],comb_r[[7]],comb_r[[9]])

If your rasters are already named you can just order them like so:
ordered_names <- c("1", "2", "3", "4", "5", "6", "7", "8", "9", "10")
ordered_stack <- comb_r[[ordered_names]]

Related

Circular heat maps in R?

Similar questions have been asked here and here, however, none of the other answers solve my problem.
Im trying to join together two (or more) separate heat maps and turn them into a circle. Im trying to achieve something like the image below (which I made by following the circlize package tutorial found here:
In my data, I have multiple matrices, where each matrix represents a different year. I want to try and create a circular heat map (like the one in the image) where each section of the circular heatmap is a single year.
In my example below, I am just using 2 years (so 2 heat maps) but I cant seem to get it to work:
library(circlize)
# create matrix
mat1 <- matrix(runif(80), 10, 8)
mat2 <- matrix(runif(80), 10, 8)
rownames(mat1) <- rownames(mat2) <- paste0('a', 1:10)
colnames(mat1) <- colnames(mat2) <- paste0('b', 1:8)
# join together
matX <- cbind(mat1, mat2)
# set splits
split <- c(rep('a', 8), rep('b', 8))
split = factor(split, levels = unique(split))
# create circular heatmap
col_fun1 = colorRamp2(c(0, 0.5, 1), c("blue", "white", "red"))
circos.heatmap(matX, split = split, col = col_fun1, rownames.side = "inside")
circos.clear()
The above code makes:
Im not sure where I am going wrong!? As when I use the ComplexHeatmap package, I am splitting the matrices correctly, as shown below:
# using ComplexHeatmap package
library(ComplexHeatmap)
Heatmap(matX, column_split = split, show_row_dend = F, show_column_dend = F)
Any suggestions as to how I could achieve this?

How do I display box-plots of different data sets above each other in R?

new to R and just wondering is it possible to display these two box plots either side by side or above each other to allow for comparison, rather then producing two seperate box plots.
PBe <- PB$`Enterococci (cfu/100ml)`
BRe <- BR$`Enterococci (cfu/100ml)`
boxplot(BRe, horizontal = TRUE, col = "3", outline=FALSE)
boxplot(PBe, horizontal = TRUE, col = "4", outline=FALSE)
You could use the boxplot function directly:
boxplot(list(BRe = BRe, PBe = PBE), col = c(3, 4))
You could add all the other parameters as you wish
We obviously don't have your data, so let's make a minimal reproducible example.
First we create two data frames, one called PB and one called BR. Each has a numeric column called Enterococci (cfu/100ml) containing random numbers between 100 and 1000:
set.seed(1)
PB <- data.frame(a = sample(100:1000, 100, TRUE))
BR <- data.frame(a = sample(100:1000, 50, TRUE))
names(PB) <- "Enterococci (cfu/100ml)"
names(BR) <- "Enterococci (cfu/100ml)"
Now, if we extract these columns as per your code, we can concatenate them together using c
PBe <- PB$`Enterococci (cfu/100ml)`
BRe <- BR$`Enterococci (cfu/100ml)`
value <- c(PBe, BRe)
Now, the trick is to create another vector that labels which data frame these numbers originally came from as a factor variable. We can do that with:
dataset <- factor(c(rep("PB", nrow(PB)), rep("BR", nrow(BR))))
And now we can just call plot on these two vectors. This will automatically give us a side-by-side boxplot:
plot(dataset, value, xlab = "Data set", ylab = "Enterococci (cfu/100ml)")
If you would prefer it to be horizontal, we can do:
boxplot(value ~ dataset, horizontal = TRUE,
ylab = "Data set",
xlab = "Enterococci (cfu/100ml)")

How to add label in table() in R

I want to print 2*2 confusion matrix and label it. I am using table() in r.
I want to add predicted and Reality label . Can anybody suggest me , how can I do it?
This is a similar problem to the one in this question. You can follow that approach,
but simplify things a bit by just using a matrix to hold the values, and
just setting its dimension names to "predicted" and "observed":
# create some fake data (2x2, since we're building a confusion matrix)
dat <- matrix(data=runif(n=4, min=0, max=1), nrow=2, ncol=2,
dimnames=list(c("pos", "neg"), c("pos", "neg")))
# now set the names *of the dimensions* (not the row/colnames)
names(dimnames(dat)) <- c("predicted", "observed")
# and we get what we wanted
dat
# output:
# observed
# predicted pos neg
# pos 0.8736425 0.7987779
# neg 0.2402080 0.6388741
Update: #thelatemail made the nice point in the comments that you can specify dimension names when creating tables. The same is true of matrices, except you supply them as names of the dimnames list elements when calling matrix(). So here's an even more compact way:
matrix(data=runif(n=4, min=0, max=1), nrow=2, ncol=2,
dimnames=list(predicted=c("pos", "neg"), observed=c("pos", "neg")))

classify raster stack with levelplot (RasterVis)

i have a raster stack of 7 rasters with quite varying data ranges and not all of the rasters adhere to quite the same range. (some are low value ranges, some much higher). Using the levelplot function with the stack, it plots nicely enough, eg:
r <- raster(ncol=10,nrow=10)
r[] <- sample(c(1:3),size=100,replace=T)
r1 <- raster(ncol=10,nrow=10)
r1[] <- sample(c(1:9),size=100,replace=T)
r2 <- raster(ncol=10,nrow=10)
r2[] <- sample(c(5:15),size=100,replace=T)
r3 <- raster(ncol=10,nrow=10)
r3[] <- sample(c(3:35),size=100,replace=T)
s <- stack(r,r1,r2,r3)
breaks <- 7
my.at <- round(seq(min(minValue(s)), max(maxValue(s)), length.out = breaks),digits=2)
myColorkey <- list(at=my.at,height=0.95, width=1, labels=list(at=my.at,cex=1.1))
cols <- (brewer.pal(length(my.at)-1, "YlGnBu"))
levelplot(s,at=my.at,col.regions=cols,colorkey = myColorkey)
As you can see, the images with the lower value data are one colour (Actually in my real data most of the plots are one colour as the data range is dominated by two latter rasters). Using the levelplot function, i would like to reclassify the entire raster stack, teasing out some patterns in the lower value rasters with some classes that i define and simply assign anything over value x (perhaps 10 in the sample data above) to be one colour.
the usual method of ratifying and setting levels will not work for a stack and any workaround i have tried (using a matrix and reclassify) will not force more levels than there are classes for a raster
this is my workaround, using the standard legend, but i'd like to use ratify etc if possible;
# using s from above
m <- c(0,1,1, 1,3,2, 3,6,3, 6,10,4, 10,35,5)
mat <- matrix(m, ncol=3, byrow=TRUE)
src <- reclassify(s, mat)
breaks <- nrow(mat)
my.at <- (0:breaks)
myColorkey <- list(at=my.at,height=0.95, width=1, labels=list(at=my.at+0.5,labels=c("0-1","1-3","3-6","6-10","10-35"),cex=1.1))
cols <- (brewer.pal(length(my.at)-1, "YlGnBu"))
levelplot(src,at=my.at,col.regions=cols,colorkey = myColorkey)

Entering cell values from a matrix into a levelplot made in lattice in r

I am aware of this thread - How to show matrix values on Levelplot
and this thread - Showing data values on levelplot in R
that ask similar questions. But I don't quite see how I can adapt the code to what I am trying.
I have a matrix (M1) that I can make a levelplot from. What I would like to do is add the respective value from each 'cell' in M1 to the corresponding 'cell' in the levelplot. I have been trying with panel.levelplot but I just can't figure out how to define the variables x,y,z.
A follow up question would be... if I can create a levelplot from matrix M1, but I want to add the values from another matrix (M2) of exactly the same size. How can this be done?
Example data:
#Matrix1
M1 <- matrix(0, nrow=5, ncol=5)
M1[upper.tri(M1, diag = FALSE)]<-1
M1
#Matrix2
M2<-matrix(sample.int(25, replace = TRUE), nrow = 5, ncol = 5)
M2
#This makes a levelplot but how to add the values from a) Matrix M1, b) Matrix M2
levelplot(M1[1:ncol(M1),ncol(M1):1])
Following the first question , for example, you just slightly modify it to include M2 values.
myPanel <- function(x, y, z, ...) {
panel.levelplot(x,y,z,...)
panel.text(x, y, M2[cbind(x,y)]) ## use handy matrix indexing
}
Then you get your result :
levelplot(M1,panel=myPanel)
To orient whole thing so that M1[1,1] is in the upper left corner, as it would be if you simply printed M1, do it this way (see comment from Bryan):
M3 <- t(M1[nrow(M1):1,])
levelplot(M3, panel = myPanel)

Resources