Renaming variables in raster data using substr - r-raster

I downloaded worldclimate data and changed it into raster data.
There are names like wc2.1_5m_bio_1 until 19, and I want to rename these variables to bio_1 (start = 10, stop = 16) using substr function. However, I dont know how to make it permanent on the raster data.
substr(clim#ptr[[“names”]], start = 10, stop = 16)
It gives what I want but not permanent. So everytime I reload the raster data, it still has the original long name.

You can get and set the names like this:
library(terra)
s <- rast(system.file("ex/logo.tif", package="terra"))[[1:2]]
names(s)
#[1] "red" "green"
names(s) <- substr(names(s), 1, 1)
names(s)
#[1] "r" "g"
(you should never directly use the #ptr slot)
To make this permanent you need to write the data to a new file:
writeRaster(s, "test.tif", overwrite=TRUE)
rast("test.tif")
#class : SpatRaster
#dimensions : 77, 101, 2 (nrow, ncol, nlyr)
#resolution : 1, 1 (x, y)
#extent : 0, 101, 0, 77 (xmin, xmax, ymin, ymax)
#coord. ref. : +proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs
#source : test.tif
#names : r, g
#min values : 0, 0
#max values : 255, 255

Related

How to create a crosstab with variable labels for PDF output in R markdown

I would like to make a table in R markdown that prints a crosstabulation of two variables and includes the variable name above it and on the left side. Also, I need to print this to a PDF so I require code that is compatible with kable("latex").
Reproducible example:
set.seed(143)
x <- sample(x = c("yes", "no"), size = 20, replace = TRUE)
y <- sample(x = c("yes", "no"), size = 20, replace = TRUE)
table(x,y) %>%
kable("latex") %>%
pack_rows("X", 1, 2) %>%
add_header_above(c(" ", "Y" = 2))
Which gives the following output:
However I would like it to look like this (created in Word for example):

rasterFromXYZ missing value where TRUE/FALSE needed

I have been having some strange error messages from the rasterFromXYZ function in the R raster package. Here is an example
library(raster)
xyz <- data.frame(x = c(5.463636, 5.481818, 5.5), y = c(51.42727, 51.42727, 51.42727), z = c(1.2,1.3,1.6))
r <- rasterFromXYZ(xyz)
##error
Error in if (nc > (2^31 - 1)) return(FALSE) :
missing value where TRUE/FALSE needed
In addition: Warning message:
In min(dy) : no non-missing arguments to min; returning Inf
##specifying the resolution as 1
r <- rasterFromXYZ(xyz, res = 1)
##different error
Error in rasterFromXYZ(xyz, res = 1) : x cell sizes are not regular
The x coordinates are perfectly regular. What am I doing wrong?
The x-coordinates are OK, but there is only one unique y-coordinate value. So there is no way to guess the vertical resolution.
xyz
# [,1] [,2] [,3]
#[1,] 5.463636 51.42727 1.2
#[2,] 5.481818 51.42727 1.3
#[3,] 5.500000 51.42727 1.6
If you set the resultion to 1 that does not match the x-coordinates, but you can do
rasterFromXYZ(xyz, res=c(NA, 1))
#class : RasterLayer
#dimensions : 1, 3, 3 (nrow, ncol, ncell)
#resolution : 0.018182, 1 (x, y)
#extent : 5.454545, 5.509091, 50.92727, 51.92727 (xmin, xmax, ymin, ymax)
#crs : NA
#source : memory
#names : layer
#values : 1.2, 1.6 (min, max)
The development version now gives a better error message:
r <- rasterFromXYZ(xyz)
#Error in rasterFromXYZ(xyz) : more than one unique y value needed

How to remain same resolution and coordinate reference after calculation for raster in R

#####first import all files in a single folder as a list #####
rastlist <- list.files(path = ".", pattern='.tif$', all.files=TRUE, full.names=FALSE)
######load them in a stack ######
allrasters <- stack(rastlist)
input_stack1 <- stack(brick(allrasters))
####### create array #######
try <- array(input_stack1, dim=c(13056, 4846, 2,1))
####### replace -3000 with NA #######
try[try==-3000]<-NA
input_array<-aperm(try, c(2,1,3,4))
####### convert back #######
output_stack1<-stack(brick(array(input_array, c(4846, 13056, 2))))
>input_stack1
class : RasterStack
dimensions : 4846, 13056, 63269376, 2 (nrow, ncol, ncell, nlayers)
**resolution : 250, 250 (x, y)**
extent : -1253475, 2010525, 2211480, 3422980 (xmin, xmax, ymin, ymax)
**crs : +proj=utm +zone=51 +datum=WGS84 +units=m +no_defs**
names : MOSAIC_TMP_2019001.hdfout.250m_16_days_NDVI, MOSAIC_TMP_2019017.hdfout.250m_16_days_NDVI
min values : -3000, -3000
max values : 9996, 9996
>output_stack1
class : RasterStack
dimensions : 4846, 13056, 63269376, 2 (nrow, ncol, ncell, nlayers)
**resolution : 7.659314e-05, 0.0002063558 (x, y)**
extent : 0, 1, 0, 1 (xmin, xmax, ymin, ymax)
**crs : NA**
names : layer.1, layer.2
min values : -2000, -2000
max values : 9996, 9996
don't know why the resolution and crs in output_stack1 change. Can everyone tell me how to remain the resolution and crs in input_stack1 after replace -3000 as NA in output_stack1
I am not sure why you are doing what you are doing, but it suggests that you may want to look at the manual of the raster package or study the materials here
With a list of filenames create a RasterStack
library(raster)
f <- system.file("external/rlogo.grd", package="raster")
rastlist <- rep(f, 3)
s <- stack(rastlist)
(do not call stack(brick()) after that; that does not do anything useful, but could take a lot of time.)
Now reclassify the RasterStack. In this example using 255 instead of -3000.
r <- reclassify(s, cbind(255, NA))
r
#class : RasterBrick
#dimensions : 77, 101, 7777, 9 (nrow, ncol, ncell, nlayers)
#resolution : 1, 1 (x, y)
#extent : 0, 101, 0, 77 (xmin, xmax, ymin, ymax)
#crs : +proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs
#source : memory
#names : red.1, green.1, blue.1, red.2, green.2, blue.2, red.3, green.3, blue.3
#min values : 0, 0, 0, 0, 0, 0, 0, 0, 0
#max values : 254, 254, 254, 254, 254, 254, 254, 254, 254

Problem with the "stackApply" function in R

I have a problem with the "stackApply" function from the raster-package. First I want to stack three raster layers (each layer has one band) - that works. And then I want to create a raster-object that shows in which of the three bands/layers the minimum value occurs (each pixel in the raster layers has a different value). But I get various error messages. Does anyone have an idea how I can solve the problem?
Thank you
stacktest<-stack(test,test1,test2)
min_which <- stackApply(stacktest, indices=1, fun=function(x, na.rm=NULL)which.min(x))
Error in setValues(out, v) : values must be a vector
Error in is.infinite(v) : not implemented standard method for type 'list'
Here is a minimal, self-contained, reproducible example:
Example data from ?stackApply
library(raster)
r <- raster(ncol=10, nrow=10)
values(r) <- 1:ncell(r)
s <- stack(r,r,r,r,r,r)
s <- s * 1:6
Now use these data with your function (I removed the na.rm=NULL as it is not used)
w <- stackApply(s, indices=1, fun=function(x, ...) which.min(x) )
w
#class : RasterLayer
#dimensions : 10, 10, 100 (nrow, ncol, ncell)
#resolution : 36, 18 (x, y)
#extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
#crs : +proj=longlat +datum=WGS84 +no_defs
#source : memory
#names : index_1
#values : 1, 1 (min, max)
Same for which.max
w <- stackApply(s, indices=1, fun=function(x, na.rm=NULL) which.max(x) )
w
# (...)
#values : 6, 6 (min, max)
This suggest it works fine. In most cases that means that you probably have cells that are NA
s[1:10] <- NA
w <- stackApply(s, indices=1, fun=function(x, ...) which.min(x) )
# Error in setValues(out, v) : values must be numeric, logical or factor
It is easy to see why this error occurs
which.min(3:1)
#[1] 3
which.min(c(3:1, NA))
#[1] 3
which.min(c(NA, NA, NA))
#integer(0)
If all values are NA, which.min does not return NA as expected. Instead it returns an empty vector. That can be fixed like this
which.min(c(NA, NA, NA))[1]
#[1] NA
And you can do
w <- stackApply(s, indices=1, fun=function(x, ...) which.min(x)[1] )
However, using stackApply with indices=1 is not a good approach. You should generally use calc to compute cell values across all layers.
y <- calc(s, function(x) which.min(x)[1])
But in this case you can use the more straightforward
z <- which.min(s)

Lua REGEX, catch parenthesis

How catch the values (r = 32, g = 36, b = 51) from this data above?
$color1: rgba(32, 36, 51, 1);
I try:
v = "$color1: rgba(32, 36, 51, 1);"
id, r, g, b = v.match(v, "%$color(%d+)%:%s+rgba%((%d+)%,%s+(%d+)%,%s+(%d+)%,%s+%d+%)%;") or 0, 0, 0, 0
But does not work.
v = "$color1: rgba(32, 36, 51, 1);"
string.gsub(v, "%((%d+),%s(%d+),%s(%d+)", function(r, g, b) print(r, g, b) end)
Output: 32 36 51
Gsub finds occurrences of a pattern in a string and will either replace text with text or in this case, run a function.
I start my pattern with %( because I assume you're only going to run this function on a string that always looks like the one you've given, so there can be no false positives, so it will be pretty safe to just start at the first opening parenthesis.
Each %d+ finds one or more digit, and it is wrapped in parentheses so the function can find it later. ,%s finds a comma and a space between the digits.
function(r, g, b) acts where r, g and b are the first, second and third set found in parenthesis.
Your id, r, g, b = v.match(v, "%$color(%d+)%:%s+rgba%((%d+)%,%s+(%d+)%,%s+(%d+)%,%s+%d+%)%;") or 0, 0, 0, 0 line is parsed by Lua as
id = v:match(pattern) or 0
r = 0
g = 0
b = 0
Since there is a match, the id variable is set to the capturing group 1 value, the rest is assigned with zeros.
You may fix this assignment using tables:
result = {string.match(v, "%$color(%d+):%s+rgba%((%d+),%s+(%d+),%s+(%d+),%s+%d+%);")}
id, r, g, b = result[1] or 0, result[2] or 0, result[3] or 0, result[4] or 0
See the Lua demo.
NOTE:; and , are not special Lua pattern characters, hence I removed % escapes in front of them in the pattern.