R convert raster to individual polygons - r

I'm sure if this is possible in R, and if someone knows of a way to do this with some other program please let me know
Currently I have a raster, and I need to turn a group of pixels into an NA group if there isn't a large enough cluster. My current thought process was to convert the raster to a polygon, and then calculate the polygons area and remove the polygons if they weren't large enough. The only problem with this is that rasterToPolygon creates a single layer of polygons, and I have no way of individually indexing each one. Any ideas? Here is an example:
library(raster)
area <- raster(matrix(c(1:4,1),5,5))
shape <- rasterToPolygons(area,fun=function(x){x == 1},dissolve=TRUE)

After dissolving, you can disaggregate the multipart polygon into single part polygons again. The disaggregate method for SpatialPolygons* is in the sp package (which should already be loaded if you have raster loaded).
library(sp)
shape2 <- disaggregate(shape)
shape2
## class : SpatialPolygonsDataFrame
## features : 2
## extent : 0, 1, 0, 1 (xmin, xmax, ymin, ymax)
## coord. ref. : NA
## variables : 1
## names : abc
## min values : 1
## max values : 1
Polygons will have an attribute that indicates the value their original raster value. You could then, for example, add an attribute giving each polygon a unique ID.
shape2$id <- factor(seq_len(length(shape2)))
spplot(shape2, 'id')

Related

How can I subset a raster by conditional statement in R using `terra`?

I am trying to plot only certain values from a categorical land cover raster I am working with. I have loaded it in to R using the terra package and it plots fine. However, since the original data did not come with a legend, I am trying to find out which raster value corresponds to what on the map.
Similar to the answer provided here: How to subset a raster based on grid cell values
I have tried using the following line:
> landcover
class : SpatRaster
dimensions : 20057, 63988, 1 (nrow, ncol, nlyr)
resolution : 0.0005253954, 0.0005253954 (x, y)
extent : -135.619, -102, 59.99989, 70.53775 (xmin, xmax, ymin, ymax)
coord. ref. : lon/lat WGS 84 (EPSG:4326)
source : spat_n5WpgzBuVAV3Ijm.tif
name : CAN_LC_2015_CAL_wgs
min value : 1
max value : 18
> plot(landcover[landcover == 18])
Error: cannot allocate vector of size 9.6 Gb
However, this line takes a very long time to run and produces a vector memory error. The object is 1.3 kb in the global environment and the original tif is about 300 mb.
You can use cats to find out which values correspond to which categories.
library(terra)
set.seed(0)
r <- rast(nrows=10, ncols=10)
values(r) <- sample(3, ncell(r), replace=TRUE) - 1
cls <- c("forest", "water", "urban")
levels(r) <- cls
names(r) <- "land cover"
cats(r)[[1]]
# ID category
#1 0 forest
#2 1 water
#3 2 urban
To plot a logical (Boolean) layer for one category, you can do
plot(r == "water")
And from from the above you can see that in this case that is equivalent to
plot(r == 1)
I think I found the solution to write the conditional within the plot function as below:
plot(landcover == 18)
For those looking for a reproduceable example, just load the rlogo:
s <- rast(system.file("ex/logo.tif", package="terra"))
s <- s$red
plot(s == 255)

Separating raster by land use attribute in R

I am new to R and trying to extract a subset of values from a raster file. I am using the Ontario Land Cover Compilation (OLCC) v.2.0 and want to only extract impervious cover values within my buffer regions. According to the Data Specifications there are classification names for land use classes and associated codes. I only want to extract data from the Community/Infrastructure name (code 27). I have uploaded the entire raster into R. Is there a way to separate the raster by code name/class? If I get the separated raster subset I know how to extract within my buffer region from there.
I have tried the raster brick function to see if it would recognize the code names and separate them into different layers automatically but this didn't work. I saw another post where raster attributes were extracted by class, but I am not sure how the land use classes are being separated and defined in R here.
Here is some example data
library(terra)
#terra 1.5.6
set.seed(0)
x <- rast(nrows=10, ncols=10, names="cover")
values(x) <- sample(3, ncell(x), replace=TRUE) - 1
levels(x) <- c("forest", "water", "urban")
Inspect
x
#class : SpatRaster
#dimensions : 10, 10, 1 (nrow, ncol, nlyr)
#resolution : 36, 18 (x, y)
#extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
#coord. ref. : lon/lat WGS 84
#source : memory
#name : cover
#min value : forest
#max value : water
levels(x)[[1]]
#[1] "forest" "water" "urban"
cats(x)[[1]]
# ID category
#1 0 forest
#2 1 water
#3 2 urban
So if you were interested in extracting the "urban" areas only, you can see that the ID (cell value) for that class is 2. And you can do
urban <- x == 2
plot(urban)
text(x)
urb <- x == "urban"
It should also have been possible to do
urb <- x == "urban"
But that may be offset by one class in some cases. To use this safely, you need terra 1.5-7 (currently the development version)
Also, if there are multiple categories, you may first need to activate the category you are interested in; like so:
activeCat(x) <- "cover"

calculating centroid of raster

I have a list (s) containing information on the probable locations of many animals in South America. For example, this is the type of stored information and what it looks like when plotted for the first individual.
Example:
> s[1]
[[1]]
class : RasterLayer
dimensions : 418, 313, 130834 (nrow, ncol, ncell)
resolution : 0.16666, 0.16666 (x, y)
extent : -86.333, -34.16842, -55.91633, 13.74755 (xmin, xmax, ymin, ymax)
coord. ref. : NA
data source : in memory
names : layer
values : 0, 1 (min, max)
> plot(s[[1]])
Note: the green areas are all "likely" locations and the grey areas are "unlikely" locations.
I would like to calculate the centroid of this probable location (i.e., centroid of the green area).
Below #dww suggested the following solution (which works for the simulated data), but leads to an error message with my data.
colMeans(xyFromCell(s, which(s[]==1)))
Error in xyFromCell(s[1], which(s[] == 1)) :
trying to get slot "extent" from an object of a basic class ("list") with no slots
To find the centroid of the cells where a raster r has the value 1, you can use
colMeans(xyFromCell(r, which(r[]==1)))
Essentially, the centroid is at the mean of the latitudes/longitudes of the subsetted locations.
Here's some reproducible dummy data to test on:
r = raster(matrix(sample(0:1, 10000,T), nrow=100,ncol=100))

How to get values for a pixel from a geoTIFF in R?

I'm trying to get RGB components from a geoTIFF file in R. The colours on the image correspond to different land classification types and I have a legend for each classification type in RGB components.
I'm using the raster library. My code so far is
library(raster)
my.map = raster("mygeoTIFFfile.tif")
Here is the information on the file once it has been read in:
> my.map[[1]]
class : RasterLayer
dimensions : 55800, 129600, 7231680000 (nrow, ncol, ncell)
resolution : 0.002777778, 0.002777778 (x, y)
extent : -180.0014, 179.9986, -64.99861, 90.00139 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0
data source : filepah/filename.tif
names : filename.tif
values : 11, 230 (min, max)
The specific geoTIFF file I'm working on can be found here:
http://due.esrin.esa.int/page_globcover.php
(just click on "Globcover2009_V2.3_Global_.zip")
Can someone please help me get the value from a single pixel location from this file please?
The rasterToPoints() function will convert your raster data to a matrix containing x, y, and value for each point. This will be very large, but may be what you're looking for if you want to do a broad analysis of the data.
library(raster)
map <- raster("GLOBCOVER_L4_200901_200912_V2.3.tif")
data <- rasterToPoints(map, progress="text")
head(data)
Another option is to use the extract() function to return a single point by passing a SpatialPoints object with latitude/longitude. If you only want a few individual data points, this will be a lot faster than loading the entire thing into a matrix.
library(raster)
map <- raster("GLOBCOVER_L4_200901_200912_V2.3.tif")
extract(map, SpatialPoints(cbind(-123.3680884, 48.4252848)))
It seems that you are asking the wrong question.
To get a value for a single pixel (grid cell), you can do use indexing. For example, for cell number 10,000 and 10,001 you can do r[10000:10001].
You could get all values by doing values(r). But that will fail for a very large raster like this (unless you have lots of RAM).
However, the question you need answered, it seems, is how to make a map by matching integer cell values with RGB colors.
Let's set up an example raster
library(raster)
r <- raster(nrow=4, ncol=4)
values(r) <- rep(c(11, 14, 20, 30), each=4)
And some matching RGB values
legend <- read.csv(text="Value,Label,Red,Green,Blue
11,Post-flooding or irrigated croplands (or aquatic),170,240,240
14,Rainfed croplands,255,255,100
20,Mosaic cropland (50-70%) / vegetation (grassland/shrubland/forest) (20-50%),220,240,100
30,Mosaic vegetation (grassland/shrubland/forest) (50-70%) / cropland (20-50%) ,205,205,102")
Compute the color code
legend$col <- rgb(legend$Red, legend$Green, legend$Blue, maxColorValue=255)
set up a "color table"
# start with white for all values (1 to 255)
ct <- rep(rgb(1,1,1), 255)
# fill in where necessary
ct[legend$Value+1] <- legend$col
colortable(r) <- ct
plot
plot(r)
You can also try:
tb <- legend[, c('Value', 'Label')]
colnames(tb)[1] = "ID"
tb$Label <- substr(tb$Label, 1,10)
levels(r) <- tb
library(rasterVis)
levelplot(r, col.regions=legend$col, at=0:length(legend$col))

Getting Data out of raster file in R

I'm new to raster files, but they seem to be the best way to open up the large gov't files that have all the weather data, so I'm trying to figure out how to use them. For reference, I'm downloading the files located here (just some run of the mill weather stuff). When I use the raster package of R to import the file like this
> r <- raster("/path/to/file.grb")
Everything works fine. I can even get a little metadata when I type in
> r
class : RasterLayer
band : 1 (of 37 bands)
dimensions : 224, 464, 103936 (nrow, ncol, ncell)
resolution : 0.125, 0.125 (x, y)
extent : -125.0005, -67.0005, 25.0005, 53.0005 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=longlat +a=6371200 +b=6371200 +no_defs
data source : /path/to/file.grb
names : NLDAS_MOS0125_H.A20140629.0100.002
All I've managed to do at this point is index the raster in a very obvious way.
> r[100,100]
267.1
So, I guess I can "index" it, but I have no idea what the number 267.1 means. It's certainly not all there is in the cell. There should be a bunch of variables including, but not limited to, soil moisture, surface runoff, and evaporation.
How can I access this information in the same way using R?
# create two rasters
r1 <- raster(matrix(ncol = 10, nrow = 10, runif(100)))
r2 <- raster(matrix(ncol = 10, nrow = 10, runif(100)))
# creates a raster stack -- the stack (or brick function) allows you to
# to use multilayer band rasters
# http://www.inside-r.org/packages/cran/raster/docs/stack
st_r <- stack(r1, r2)
# extract values -- will create a matrix with 100 rows and two columns
vl <- getValues(st_r)
r <- raster("/path/to/file.grb")
values <- getValues(r)
You can read about the function here:
http://www.inside-r.org/packages/cran/raster/docs/values
I believe that the problem is that you are using raster and not stack. The raster function results in a single layer (matrix) whereas stack or brick read an array with all of the raster layers. Here is an example that demonstrates extracting values using an [i,j,z] index.
library(raster)
setwd("D:/TMP")
download.file("ftp://hydro1.sci.gsfc.nasa.gov/data/s4pa/NLDAS/NLDAS_MOS0125_H.002/2014/180/NLDAS_MOS0125_H.A20140629.0000.002.grb",
destfile="NLDAS_MOS0125_H.A20140629.0000.002.grb", mode="wb")
r <- stack("NLDAS_MOS0125_H.A20140629.0000.002.grb")
names(r) <- paste0("L", seq(1:nlayers(r)))
class(r)
# Values for [i,j]
i=100
j=100
r[i,j]
# Values for i,j and z at layer(s) 1, 5 and 10
z=c(1,5,10)
r[i,j][z]

Resources