Using R to change raster projection - r

I'm trying to change raster projection using R and the raster package. The input raster projection is Lambert Azimuthal; the parameters are here:
Coordinate System:
Lambert_Azimuthal_Equal_Area
False_Easting: 4321000,000000
False_Northing: 3210000,000000
Central_Meridian: 10,000000
Latitude_Of_Origin: 52,000000
GCS_ETRS_1989
Datum: D_ETRS_1989
Prime Meridian: 0
PROJCS
["ETRS_1989_LAEA",
GEOGCS ["GCS_ETRS_1989",
DATUM ["D_ETRS_1989",
SPHEROID ["GRS_1980",6378137.0,298.257222101]],
PRIMEM["Greenwich",0.0],
UNIT["Degree",0.0174532925199433]],
PROJECTION["Lambert_Azimuthal_Equal_Area"],
PARAMETER["False_Easting",4321000.0],
PARAMETER["False_Northing",3210000.0],
PARAMETER["Central_Meridian",10.0],
PARAMETER["Latitude_Of_Origin",52.0],
UNIT["Meter",1.0]]
I need to convert them to simple rasters in ESRI ASCII format, using longitude and latitude coordinates, with a Mercator-style projection, with a cell size of 0.1 degrees (I hope I explain myself well enough, because I don't have enough GIS skills, sorry). What I need are rasters in format .ASC where each value of the raster corresponds to a single cell of size N x N, where N is in degrees (e.g. 0.1 degrees), and the raster coordinates are in longitude/latitude.
I tried to use raster library in R, and follow examples found for the projectRaster function. But after many attempts using many several parameters, I wasn't be able to make it correctly. I think I'm not using the correct parameters for projection, datum, or something like this.
Here's what I tried. I load the raster in R, then I set its projection using:
>crs(r)<-"+proj=laea +lat_1=52 +lon_0=-10 +ellps=GRS80"
Then I define the output projection and I try the conversion and save:
>newproj <- "+proj=lonlat +lat_1=52 +lon_0=-10 +ellps=WGS84"
>pr2 <- projectRaster(r, crs=newproj, res=0.1)
>writeRaster(pr2, "newraster.asc", overwrite=TRUE)
No error messages, but resulting raster is not correctly projected (country borders don’t match, countries are slightly distorted).
Thanks for any help!

Given the description of the projection you provide, this seems wrong:
crs(r) <- "+proj=laea +lat_1=52 +lon_0=-10 +ellps=GRS80"
As you do not include the false northing and easting parameters; and lat_1 should probably be lat_0. This may be better:
crs(r) <- "+proj=laea +lat_0=52 +lon_0=10 +x_0=4321000 +y_0=3210000 +ellps=GRS80 +units=m"
This also looks odd:
newproj <- "+proj=lonlat +lat_1=52 +lon_0=-10 +ellps=WGS84"
How about
newproj <- "+proj=longlat +datum=WGS84"

Related

ggplot can find lng and lat in dataset but leaflet cannot, "Need '+proj=longlat +datum=WGS84' "

I have a dataset form the public repo https://github.com/highsource/verbundkarte
Reading the dataset with st_read and plotting it with ggplot yields a beautiful map with correct lng and lat data.
df <- st_read("~/Verkehrsverbunde.shp")
map <- ggplot(df) + geom_sf(aes(fill=SHORTNAME))
I therefore assume, that the lng/lat values are included in the variable df$geometry. However, if I use leaflet, no matter what I try I end up with an error. For instance
df%>% leaflet() %>%
addProviderTiles("CartoDB") %>%
addPolygons(label = htmlEscape(verbunddaten$SHORTNAME)) %>%
setView(lng = 10.3, lat = 51.9, zoom = 5.1)
ends up with
Warning messages:
1: sf layer is not long-lat data
2: sf layer has inconsistent datum (+proj=tmerc +lat_0=0 +lon_0=9 +k=1 +x_0=3500000 +y_0=0 +datum=potsdam +units=m +no_defs ).
Need '+proj=longlat +datum=WGS84'
I found this beautiful conversation of which I understood basically nothing. Reading the data with readOGR as suggested here doesn't solve my problem.
How do I force leaflet to assume the same longlat and EPSG as ggplot?
The data in your Verkehrsverbunde.shp shapefile is in a custom traverse mercator projection, where coordinates are expressed in meters. By contrast, r-leaflet expects data to be expressed in degrees of latitude-longitude, which would look like an equirectangular projection if/when plotted.
I'll guess that, contrary to your belief, ggplot is not using latitude and longitude in degrees, but rather northing and easting values in meters. The representation of the data might look similar for small areas.
In GIS terms, your data is using the EPSG:31467 CRS (Coordinate Reference System), as can be inferred by proj=tmerc and datum=postdam; r-leaflet expects data in the EPSG:4326 CRS.
The approach here would be to reproject your data, so that coordinates are in latitude-longitude as expected. There are plenty of ways to do this; running ogr2ogr -t_srs epsg:4326 Verkehrsverbunde-latlng.shp Verkehrsverbunde-latlng.shp on a command line, using R, or using QGIS, amongst other methods.

How can I project a raster in lat-long coordinates to UTM, for plotting in tmap?

I have a map with an elevation raster that is in lat/long coordinates but I now need to display the map in easting/northing. How can I accomplish this?
I have tried reprojecting the raster from lat/long to UTM but this warps the map (I assume for reasons discussed in this SO post).
A minimal working example follows a description of the code that I am using to produce the map in lat/long coordinates. I used a manually defined bounding box, extent, to download the elevation raster of interest from FedData. I then plotted the raster using tmap.
# - Libraries ----
library(proj4)
library(FedData)
library(rgdal)
library(tmap)
# extent defined manually
extent <- rgeos::readWKT("POLYGON((-118.25 36.45, -118.25 36.6, -118.25 36.9, -118.8 36.9, -118.8 36.45, -118.25 36.45))")
# define shape polygon on lat/long coordinates
proj4string(extent) <- "+proj=longlat +ellps=GRS80 +datum=NAD83 +no_defs"
# - Get national elevation raster ----
# download National Elevation Database elevation data in extent
# default resolution is 1 arcsecond (res="1);
# to get 1/3 arcsecond (res="13)
ned_raster<-FedData::get_ned(template=extent, label="ned_raster", res="1", force.redo = T)
# - Plot with tmap ----
tm_shape(ned_raster,unit.size=1)+
tm_graticules() +
tm_raster(legend.show=FALSE)
Update I'm updating the question with some additional clarification after Robert Hijmans' answer. I am including the code that I used for the reprojection here:
ned_raster2 <- raster::projectRaster(ned_raster, crs=CRS("+proj=utm +init=epsg:26711 +zone=11 +north +no_defs"))
The output is comparable to the one in the map you included in your answer. By modifying the bounding box with tmaptools::bb I can clip the map with tmap so that the projection is correct but it does not "appear" warped:
# - Project from angular to planar ----
ned_raster2 <- raster::projectRaster(ned_raster, crs=CRS("+proj=utm +init=epsg:26711 +zone=11 +north +no_defs"))
# redefine extent/bounding box
e2 = tmaptools::bb(ned_raster2)
e2 = e2*c(1.01,1.001,.99,.999)
# - Plot with tmap ----
tm_shape(ned_raster2,unit.size=1,bbox=e2)+
tm_graticules(n.x=5) +
tm_raster(legend.show=FALSE)
From this, how can I include the appropriate axes (in easting/northing) on this map?
I now need to display the map in easting/northing.
I understand that in stead of angular (lon/lat) coordinates you want to use planar (Cartesian) coordinates. That means that you need to choose an appropriate coordinate reference system (CRS). You say you used UTM, and that could be reasonable, but you found that the results are "warped". You should show the code you used because you probably made a mistake. There always is some distortion, but for a small area like this is would not be an issue if you specify the CRS correctly. (otherwise, explain "warped" and why it matters.)
For example
library(raster)
library(FedData)
# extent defined manually
e <- as(extent(-118.8, -118.25, 36.45, 36.9), "SpatialPolygons")
crs(e) <- "+proj=longlat"
ned <- FedData::get_ned(template=e, label="ned_raster", res="1", force.redo = T)
ned2 <- projectRaster(ned, crs="+proj=utm +zone=11")
plot(ned2)
For larger areas you cannot use UTM and you would need to use another CRS.
Alternatively, you could create grid-lines (graticule) from the projected raster, store their coordinates, and transform these back to longlat. That would be a bit odd. Normally, one might want to show longlat coordinates on a otherwise projected (planar) map.

How read disk image file (.img) in R [duplicate]

I am working with U.S. National Landcover Dataset (NLCD) to classify habitat type at more than 150 sites across the northeast U.S. The dataset is very large (15GB) so I cannot upload it here, but it comes in .img format at 30m resolution.
I have GPS coordinates for the center point of all the sites. I would like to be able to extract the proportion of landcover classes in a 1 square kilometer around the point. My questions are:
1) How do I upload .img files into r?
2) How do I extract the information from around the GPS coordinates as proportions of the different habitat classes?
Has anyone worked with this dataset in r before? If so I could really use the help.
Cheers,
Israel
Use the raster package which can process the files from disk, only reading in chunks at a time.
the raster package has an extract function with a buffer argument. set your buffer to the appropriate value (1000 if your map units are metres and you want a km radius)
Thanks to mnel. I have gotten the basic idea to work (code below). Now if anyone could give me a pointer on how to calculate the proportion of each category for every coordinate. The extract function gives me matrices of values for each set of coordinates. Is there a way to summarize this data?
#load in map and locality data
NLCD<-raster ('NLCD2006/NLCD2006.img')
sites<-read.csv('sites.csv', header=T)
#crop site data to just latitude and longitude
sites<-sites[,4:5]
#convert lat/lon to appropirate projection
str (sites)
coordinates(sites) <- c("Longitude", "Latitude")
proj4string(sites) <- CRS("+proj=longlat +ellps=WGS84 +datum=WGS84")
sites_transformed<-spTransform(sites, CRS("+proj=aea +lat_1=29.5 +lat_2=45.5 +lat_0=23 +lon_0=-96 +x_0=0 +y_0=0 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs"))
#plot the map
plot (NLCD)
#add the converted x y points
points (sites_transformed, pch=16, col="red", cex=.75)
#extract values to poionts
Landcover<-extract (NLCD, sites_transformed, buffer=1000)

Shapefiles do not overlay raster layer in R

I have hundreds of shapefiles without a coordinate reference system. My goal is the overlay the spatial polygons over the WorldClim raster layer. I used this approach before without any problems. However, this time the coordinates from my shapefiles are strange for me. Each coordinate for bounding box and coords within polygons is composed of 8 digit numbers without comma or dot to separate de decimals.
This is the bounding box from one of the shapes:
SHP bbox: xmin:-17367529, xmax:17367529, ymin:-5997367 and ymax:7052489
which are clearly different from the bounding box of the WorldClim raster layer.
WorldClim bbox: xmin=-180,xmax=180,ymin=-60 and ymax=90
When I tried to overlay the shapefile over the raster layer using plot command nothing happens.
plot(shapefile, add=T)
I understood that this is a projection problem. Then I tried to assign the same coordinate system of the WorldClim raster layer in the shapefile using the CRS function. However, the result remains the same (i.e. the shapefiles do not over the raster). In the sequence, I tried to use the spTransform function from the rgdal package to reproject the shapefile coordinates. However, because shapefile does not have any reference system the function does not work and I do not know how to reproject the shapefile in order to match with the raster layer. I've been researching for a few days about how to deal with this problem and I believe that the absence of a reference system is a key point to the problem. However, I'm failing to overcome this problem and I would like to know if someone could help how to deal with this situation.
You need to define the projection of shape files first using proj4string(meuse) or crs(shapefile)<-crs string then you can use spTransform:
library(rgdal)
data(meuse)
coordinates(meuse) <- c("x", "y")
Here you have the spatial data with x and y but you do not have the crs yet! So if you use spTransform it will fail.
summary(meuse) #proj4string : [NA] so below line fails!
meuse.utm <- spTransform(meuse, CRS("+proj=utm +zone=32 +datum=WGS84"))
# Error in spTransform(xSP, CRSobj, ...) :
# No transformation possible from NA reference system
To get around this, as mentioned above, you first need to define the projection as below:
proj4string(meuse) <- CRS(paste("+init=epsg:28992",
"+towgs84=565.237,50.0087,465.658,-0.406857,0.350733,-1.87035,4.0812"))
summary(meuse) #proj4string : epsg:28992... and then you may use spTransform
and then:
meuse.utm <- spTransform(meuse, CRS("+proj=utm +zone=32 +datum=WGS84"))

Large .img file processing in R (GIS)

I am working with U.S. National Landcover Dataset (NLCD) to classify habitat type at more than 150 sites across the northeast U.S. The dataset is very large (15GB) so I cannot upload it here, but it comes in .img format at 30m resolution.
I have GPS coordinates for the center point of all the sites. I would like to be able to extract the proportion of landcover classes in a 1 square kilometer around the point. My questions are:
1) How do I upload .img files into r?
2) How do I extract the information from around the GPS coordinates as proportions of the different habitat classes?
Has anyone worked with this dataset in r before? If so I could really use the help.
Cheers,
Israel
Use the raster package which can process the files from disk, only reading in chunks at a time.
the raster package has an extract function with a buffer argument. set your buffer to the appropriate value (1000 if your map units are metres and you want a km radius)
Thanks to mnel. I have gotten the basic idea to work (code below). Now if anyone could give me a pointer on how to calculate the proportion of each category for every coordinate. The extract function gives me matrices of values for each set of coordinates. Is there a way to summarize this data?
#load in map and locality data
NLCD<-raster ('NLCD2006/NLCD2006.img')
sites<-read.csv('sites.csv', header=T)
#crop site data to just latitude and longitude
sites<-sites[,4:5]
#convert lat/lon to appropirate projection
str (sites)
coordinates(sites) <- c("Longitude", "Latitude")
proj4string(sites) <- CRS("+proj=longlat +ellps=WGS84 +datum=WGS84")
sites_transformed<-spTransform(sites, CRS("+proj=aea +lat_1=29.5 +lat_2=45.5 +lat_0=23 +lon_0=-96 +x_0=0 +y_0=0 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs"))
#plot the map
plot (NLCD)
#add the converted x y points
points (sites_transformed, pch=16, col="red", cex=.75)
#extract values to poionts
Landcover<-extract (NLCD, sites_transformed, buffer=1000)

Resources