Converting shapefile to raster - r

I'm having an issue rasterizing a shapefile to produce points on a 0.5*0.5 grid. The shapefile represents classifications of risk level (Low-0, Medium-100, High-1000, Very High-1500) of global coral reefs to integrated threats.
I pulled the code from another example that works fine, but when I try it for my data I get nothing from the plot function. See below for the link to the shapefile and my code:
Reefs At Risk: Global Integreated Threats
# Read shapefile into R
library(rgdal)
library(raster)
int.threat.2030 <- readOGR(dsn = "Global_Threats/Integrated_Future",
layer = "rf_int_2030_poly")
## Set up a raster "template" for a 0.5 degree grid
ext <- extent(-110, -50, 0, 35)
gridsize <- 0.5
r <- raster(ext, res=gridsize)
## Rasterize the shapefile
rr <- rasterize(int.threat.2030, r)
## Plot raster
plot(rr)
Any ideas where I might be going wrong? Is it an issue with the shapefile itself?
Please and thanks!

You assumed that the polygons were in lon/lat coordinates, but they are not:
library(raster)
library(rgdal)
p <- shapefile('Global_Threats/Integrated_Future/rf_int_2030_poly.shp')
p
#class : SpatialPolygonsDataFrame
#features : 63628
#extent : -18663508, 14601492, -3365385, 3410115 (xmin, xmax, ymin, ymax)
#coord. ref. : +proj=cea +lon_0=-160 +lat_ts=0 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0
#variables : 3
#names : ID, THREAT, THREAT_TXT
#min values : 1, 0, Critical
#max values : 63628, 2000, Very High
You can either change the projection
pgeo <- spTransform(p, CRS('+proj=longlat +datum=WGS84'))
and then do something like:
ext <- floor(extent(pgeo))
rr <- raster(ext, res=0.5)
rr <- rasterize(pgeo, rr, field=1)
Or keep the orginal CRS and do something like:
ext <- extent(p)
r <- raster(ext, res=50000)
r <- rasterize(p, r, field=1)
plot(r)
Note that you are rasterizing very small polygons to large raster cells. A polygon is considered 'inside' if it covers the center of a cell (i.e. assuming a case where polygons cover multiple cells). So for these data you would need to use a much higher resolution (and then perhaps aggregate the results). Alternatively you could rasterize polygon centroids.
But none of the above is relevant really, as you are doing this all backwards. The polygons are clearly derived from a raster (look how blocky they are) and the raster is available in the dataset you point to!
So instead of rasterizing, do:
x <- raster('Global_Threats/Integrated_Future/rf_int_2030')
x
#class : RasterLayer
#dimensions : 25456, 80150, 2040298400 (nrow, ncol, ncell)
#resolution : 500, 500 (x, y)
#extent : -20037508, 20037492, -6363885, 6364115 (xmin, xmax, ymin, ymax)
#coord. ref. : NA
#data source : C:\temp\Global_Threats\Integrated_Future\rf_int_2030
#names : rf_int_2030
#values : 0, 2000 (min, max)
#attributes :
# ID COUNT THREAT_TXT
# 0 80971 Low
# 100 343535 Medium
# 1000 322231 High
# 1500 168518 Very High
# 2000 83598 Critical
Here plotting a part of Palawan:
e <- extent(c(-8990636, -8929268, 1182946, 1256938))
plot(x, ext=e)
plot(p, add=TRUE)
If you need a lower resolution see raster::aggregate. For a different coordinate reference system, see raster::projectRaster.

Related

Extracting values with SpatialPointsDataFrame from Raster returns only NAs

I am a beginner in using R for spatial data analysis and want to simply extract some values for certain locations (with lon/lat positions) from a raster stack. However, when using extract(), it returns only NAs, so I guess I made a mistake with the projection.
I loaded the lon/lat-locations into a SpatialPointsDataFrame, changed the lon/lat into numeric and set the crs to EPSG:4326.
The raster stack comes with the crs EPSG:3035, so I used "sftransform()" to project the lon/lat-locations accordingly. "compareCRS" for the two datasets gave the output "TRUE", so the projection supposedly worked.
When I try to use extract(), however, it returns only NA's.
When I put the coordinates into Google Maps, they are mapped correctly, with mapview() in R, however, they seem to be completely off grid, so I supposed something about the projection went wrong, but I have no idea what.
I hope that somebody here can help me out!
Loading in the raster stack named "texture"
> print(texture)
class : RasterStack
dimensions : 8073, 7781, 62816013, 3 (nrow, ncol, ncell, nlayers)
resolution : 500, 500 (x, y)
extent : 2635700, 6526200, 1385700, 5422200 (xmin, xmax, ymin, ymax)
crs : +proj=laea +lat_0=52 +lon_0=10 +x_0=4321000 +y_0=3210000 +ellps=GRS80 +units=m +no_defs
names : Clay_eu23, Sand_eu23, Silt_eu23
min values : 0, 0, 0
max values : 76.47613, 100.00000, 91.61756
Loading in the DF with Lon/Lat Locations
Datalogger Lat Lon
1 DL3 48.5932246 9.5576115
2 DL4 49.0160648 9.1887693
3 DL2 48.7100801 9.2141318
4 DL10 49.0038758 8.4934965
5 DL5 49.0034701 8.4954198
6 DL6 48.4183515 8.8958118
Changing the Lon/Lat columns to numeric
locations$Lon <- as.numeric(locations$Lon)
locations$Lat <- as.numeric(locations$Lat)
Setting the crs for the coordinates and creating SpatialPointsDF
coordinates(locations) <- ~Lon+Lat
proj4string(locations) <- CRS("+init=epsg:4326")
> print(locations)
class : SpatialPointsDataFrame
features : 10
extent : 1, 10, 1, 10 (xmin, xmax, ymin, ymax)
crs : +init=epsg:4326 +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0
variables : 1
names : Datalogger
min values : DL1
max values : DL9
Reprojecting the locations to the raster stack's (texture's) crs
loc_proj <- spTransform(locations, proj4string(texture))
Checking if crs is correct
compareCRS(texture, loc_proj)
Trying to extract values from rasterstack
values <- raster::extract(texture, loc_proj)
For values I only get NAs for each of the three rasters in the stack, even though when I call summary(texture) it returns valid data, and also the locations as such are valid. What did I do wrong with the projections?
Thank you very much already!!
You did
locations$Lon <- as.numeric(locations$Lon)
locations$Lat <- as.numeric(locations$Lat)
You got
print(locations)
#class : SpatialPointsDataFrame
#features : 10
#extent : 1, 10, 1, 10 (xmin, xmax, ymin, ymax)
That is, your longitude and latitude are between 1 and 10. This suggest that lon and lat were factor variables (for whatever reason); and that you made a mistake in changing them to numeric.
Consider this
x <- as.factor(c(9.5576115, 9.1887693, 9.2141318, 8.4934965, 8.4954198, 8.8958118))
as.numeric(x)
#[1] 6 4 5 1 2 3
as.numeric does not use the factor labels in the conversion. It cannot do that because these labels may contain letters. Instead, it gives you the indices
So, instead, you should do
as.numeric(as.character(x))
#[1] 9.557612 9.188769 9.214132 8.493496 8.495420 8.895812
In your code:
locations$Lon <- as.numeric(as.character(locations$Lon))
locations$Lat <- as.numeric(as.character(locations$Lat))

How do I get this raster and this shapefile on the same projection?

I have a shapefile of 10 CA counties projected in NAD83(Hard)/CA Albers. I have a raster (a netCDF file of temperature) for the entire US projected in WGS84/WGS84. I want to use the shapefile to clip the raster. I know that I need to get them on the same datum/projection first. But I've tried re-projecting the raster using raster::projectRaster(). That failed (as in the data disappeared). So then I tried re-projecting the shapefile instead using sp::spTransform(). This also failed (as in the data don't overlap). I've searched through stackoverflow but didn't see anything that seemed to help. I'm not getting an error, but projectRaster is not working and re-projecting the shapefile using spTransform doesn't produce the desired outcome. I feel like there is something specific going on here, like the transformation from WGS84 to NAD83 or loading the raster in using raster() is the problem ... but then again, it could easily be something stupid that I'm missing! =)
my shapefile and raster are here: https://www.dropbox.com/sh/l3b2syzcioeqmyy/AAA5CstBZty4ofOcVFkAumNYa?dl=0
here is my code:
library(raster) #for creating rasters from .bil files
library(rgdal) #for reading .bil files and .gdb files
library(ncdf4) #for working with ncdf files
library(sp) #for working with spatial data files
load(my_counties.RData)
myraster <- raster(myraster.nc)
my.crs <- CRS("+init=EPSG:3311") #NAD83(HARN) / California Albers (HARN is high resolution)
newraster <- projectRaster(myraster, res = 6000, crs = my.crs) #raster resolution is 1/16th of a degree
#There is data in the raster.
plot(myraster)
#but none in newraster
plot(newraster)
#Now try re-projecting the shapefile
my.crs2 <- crs(myraster)
newshapefile <- spTransform(my_counties, my.crs2)
#but the data don't overlap
plot(newshapefile); plot(myraster, add = T)
You can do
library(raster)
library(rgdal)
load("my_counties.RData")
b <- brick("myraster.nc")
Now look at b
b
#class : RasterBrick
#dimensions : 490, 960, 470400, 365 (nrow, ncol, ncell, nlayers)
#resolution : 0.0625, 0.0625 (x, y)
#extent : 234, 294, 23.375, 54 (xmin, xmax, ymin, ymax)
#crs : +proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0
#source : myraster.nc
#names : X2005.01.01, X2005.01.02, X2005.01.03, X2005.01.04, X2005.01.05, X2005.01.06, X2005.01.07, X2005.01.08, X2005.01.09, X2005.01.10, X2005.01.11, X2005.01.12, X2005.01.13, X2005.01.14, X2005.01.15, ...
#Date : 2005-01-01, 2005-12-31 (min, max)
#varname : tasmax
The horizontal extent is between 234 and 294 degrees. That points to a system with longitudes that start in Greenwich at 0 and continues to 360 (again in Greenwich). Climatologist do that. To go to the more conventional -180 to 180 degrees system:
r <- shift(b, -360)
(if your data had a global extent, you would use raster::rotate instead)
Now, transform the counties to lonlat and show that they overlap.
counties <- spTransform(my_counties, crs(r))
plot(r, 1)
lines(counties)
It is generally best to transform vector data, not raster data if you can avoid it.

Why rasterToPolygons is creating horizontal lines?

I am trying to transform a raster layer to polygons based on its values. My raster looks like this:
> labels_rast
class : RasterLayer
dimensions : 26, 64, 1664 (nrow, ncol, ncell)
resolution : 0.03000146, 0.02999809 (x, y)
extent : 352032, 352033.9, 8551454, 8551455 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=utm +zone=18 +south +datum=WGS84 +units=m +no_defs+ellps=WGS84 +towgs84=0,0,0
data source : in memory
names : layer
values : 1, 3 (min, max)
When I apply the rasterToPolygons function (dissolve = TRUE), I get extra polygons (defined by horizontal lines):
How can I avoid the creation of the polygons defined by the horizontal lines?
It works for this very similar case:
library(raster)
r <- raster(nrow=26, ncol=64, xmn=352032, xmx=352033.9, ymn=8551454, ymx=8551455, crs="+proj=utm +zone=18 +south +datum=WGS84 +units=m", vals=3)
r[, 20:40] <- 2
r[1:3, 1:60] <- 1
r[24:26, 5:64] <- 1
x <- rasterToPolygons(r, dissolve=TRUE)
plot(r)
lines(x)
I am guessing that it does not work for you because of floating point imprecision. Would have to see your file to be sure. But, if so, perhaps you can round the extent (or resolution) a little bit.
For example
res(labels_rast) <- 0.03
y <- rasterToPolygons(labels_rast, dissolve=TRUE)

Missing coordinates in raster reprojection from cylindrical equal area to lat/long using Raster function in R

I have a raster that I have reprojected from Cylindrical Equal-Area (Lambert) Central Meridian: -160. Datum: WGS 1984 (+proj=cea +lon_0=Central Meridian +lat_ts=Standard Parallel +x_0=False Easting +y_0=False Northing +ellps=WGS84) to latitude and longitude.
The original raster looks like this:
library(rasterVis)
levelplot(r)
Original raster without missing points
r
#class : RasterLayer
#dimensions : 64, 200, 12800 (nrow, ncol, ncell)
#resolution : 2e+05, 2e+05 (x, y)
#extent : -20037507, 19962493, -6363885, 6436115 (xmin, xmax, ymin, ymax)
#coord. ref. : +proj=cea +lon_0=-160 +lat_ts=Standard Parallel +x_0=False Easting +y_0=False Northing +ellps=WGS84
#data source : N:\My documents\Data\Exposure\Reefs at risk\Global_Threats\Acidification\arag_380\w001001.adf
#names : w001001
#values : 1.025163, 4.11939 (min, max)
I have been able to use the projectRaster function from the Raster package by cutting the extent of the y-axis of the raster by 0.95 to the North and South. I was having a few problems reprojecting the raster without cutting the extent (see here: https://gis.stackexchange.com/questions/220589/error-using-projectraster-in-r-error-in-if-maxy-miny-missing-value-whe/220741#220741).
#Cut y-axis values because projectRaster failed using full extent
extent(r) <- c(xmin= -20037507, xmax= 19962493, ymin= 0.95*(-6363885), ymax= 0.95*(6436115))
# Define the new Proj.4 spatial reference
sr <- "+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0"
# Project Raster
projected_r <- projectRaster(r, crs = sr, method = 'bilinear')
The problem I am having is that there are missing data in the new, reprojected raster.
levelplot(projected_r)
reprojected raster with missing points
The missing coordinates are not located in the 5% North and Souththat I cut from the extent so I am not sure why these data are missing? Any help would be appreciated!

Crop rasterLayer with SpatialPolygonDataFrame leaves out part of the target region R

library(raster)
library(ncdf4)
library(rgdal)
I am trying to crop a raster layer based on polygon: sample data (~45MB) can be found here sample data for illustration:
dat<- raster('data.nc')# make a subset
dat
class : RasterLayer
dimensions : 824, 935, 770440 (nrow, ncol, ncell)
resolution : 10000, 10000 (x, y)
extent : -5000, 9345000, -5000, 8235000 (xmin, xmax, ymin, ymax)
coord. ref. : NA
data source : C:\Users\data.nc
names : Total.Precipitation
zvar : Total.Precipitation
As coord. ref is = NA, I assign a polar stereographic projection based on information from the website of the data provider.
projj=CRS("+proj=stere +lat_0=90 +lat_ts=90 +lon_0=-100 +k=0.994 +x_0=2000000 +y_0=2000000 +datum=WGS84 +units=m +no_defs")
proj4string(dat) <- projj
#rx <- projectRaster(from=dat, crs=wgs84.p4s)
Then transform the bbox shapefile to projj
shgrid <- spTransform(Prairie.Boundaries, projj)# transform to dat spat reference
plot(dat)
plot(shgrid,add=T)# this gives
CROPPING
cr <- crop(dat, extent(shgrid))
plot(cr)
fr <- rasterize(shgrid, cr)
dat1<- mask(x=cr, mask=fr)
levelplot(dat1)
OUTPUT:
The cropped image shows only part of canada but I want all of Canada.
What did I miss within my code? Could it be the projection?
Besides I would prefer the axes labels in latlon coordinates.
Any suggestions?

Resources