Shapefiles do not overlay raster layer in R - 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"))

Related

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.

r - match spatial projections of spatial objects and overlay plots

I am trying to overlay 2 spatial objects using the plot() function. I understand that the projections of the 2 objects (of class SpatialLinesDataFrame and SpatialPolygonsDataFrame) need to be the same in order to have them visualized in the same plot. I've found similar questions here and here, but none of these can help me what I want to achieve.
Here's the coding for the SpatialPolygonsDataFrame. (v.map is a list of .kml files and loccoor is an object that stores location and corresponding x and y coordinates):
map.l<-list()
for (i in 1:length(v.map)){
ll<-ogrListLayers(paste(loccoor,"/",v.map[i],".kml",sep=""))
shp<-readOGR(paste(loccoor,"/",v.map[i],".kml",sep=""),layer=ll)
map<-spTransform(shp, CRS("+proj=longlat +datum=WGS84"))
map.l[[i]]<-map
}
plot(map.l[[1]],xlim=c(min(coor[,3]),max(coor[,3])),
ylim=c(min(coor[,2]),max(coor[,2])))
for (i in 2:length(v.map)){
plot(map.l[[i]],xlim=c(min(coor[,3]),max(coor[,3])),
ylim=c(min(coor[,2]),max(coor[,2])),add=T)
}
projection SpatialPolygonsDataFrame "map": "+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0"
projection SpatialLinesDataFrame "contours": "+proj=aeqd +ellps=WGS84 +lon_0=-XX.XXXXX +lat_0=XX.XXXXX".
I want to transform the projection of the "map" object to match that of the "contours". Simply replacing the "CRS("+proj=longlat +datum=WGS84")" of the "map" object with the projection of the "contours" object doesn't seem to work, because then the polygons are no longer plotted (visible).
Any thoughts to this would be greatly appreciated!
Here's a not very great metaphor: The coordinates are like directions, and the crs tells us what language the directions are in. So, if you change the crs, but you leave the coordinates as they are, then it would be like trying to read German directions with a Spanish dictionary.
We can translate the directions from one crs to another using sp::spTransform().
The function takes two arguments: a spatial object, and a crs.
We can use raster::crs() to get the crs from the another spatial object. So, to transform the map's coordinates (and crs) to the crs of the contours:
map <- spTransform(map, crs(contours))

Unable to properly use autokrige from automap package (R cannot read the prediction locations well)

I'm trying to use R to perform a map of interpolated frequencies of data collected from Iberian Peninsula. (something like this https://gis.stackexchange.com/questions/147660/strange-spatial-interpolation-results-from-ordinary-kriging )
My problem is that the plot is not showing the interpolated data, due to some kind of error in the atributte new_data of the autokrige function.
https://cran.r-project.org/web/packages/automap/automap.pdf
new_data:
A sp object containing the prediction locations. new_data can be a points set, a
grid or a polygon. Must not contain NA’s. If this object is not provided a default is calculated. This is done by taking the convex hull of input_data and placing around 5000 gridcells in that convex hull.
I think the problem is that R is not reading well the map transformed to poligons because if I avoid this new_data attribute I get a propper plot of the krigging values. but I do not obtain a good shape of the iberian peninsula.
Can someone help me please? I would be truly grateful
here you can see my data: http://pastebin.com/QHjn4qjP
Actual code:
now since I transform my data coordinates to UTM projection i do not get error messages but the last plot is not interpolated, the whole map appear of one single color :(
setwd("C:/Users/Ruth/Dropbox/R/pruebas")
#Libraries
library(maps)
library(mapdata)
library(automap)
library(sp)
library(maptools)
library(raster)
library(rgdal)
####################MAPA#############
#obtain the grid of the desired country
map<-getData('GADM', country='ESP', level=0)
#convert the grid to projected data
mapa.utm<-spTransform(mapa3,CRSobj =CRS(" +proj=utm +zone=29 +zone=30 +zone=31 +ellps=WGS84"))
###############################Datos#######################
#submit the data
data1<-read.table("FRECUENCIASH.txt",header=T)
head(data1)
attach(data1)
#convert longlat coordinates to UTM
coordinates(data1)<-c("X","Y")
proj4string(data1) = CRS("+proj=longlat +datum=WGS84")
data1.utm=spTransform(data1, CRS("+proj=utm +zone=29 +zone=30 +zone=31 +ellps=WGS84 "))
######################Kriging interpolation #####################
#Performs an automatic interpolation
kriging_result<-autoKrige(Z~1,data1.utm,mapa.utm,data_variogram = data1.utm)
#Plot the kriging
result1<-automapPlot(kriging_result$krige_output,"var1.pred",sp.layout = list("sp.points", data1.utm));result1
result2<-plot(kriging_result);result2
The error you get is related to the fact you are using unprojected data as input for automap. Automap can only deal with projected data. Googling for map projections should give you some background information. To project your data to a suitable projection, you can use spTransform from the sp package.
The fact that it works without newdata is because in that object the projection is not set, so automap cannot warn you. However, the results of automap with latlon input data is not reliable.

Assigning spatial coordinates to an array in R

I have downloaded a text file of data from the following link: http://radon.unibas.ch/files/us_rn_50km.zip
After unzipping I use the following lines of code to plot up the data:
# load libraries
library(fields)
# function to rotate a matrix (and transpose)
rotate <- function(x) t(apply(x, 2, rev))
# read data
data <- as.matrix(read.table("~/Downloads/us_rn_50km.txt", skip=6))
data[data<=0] <- NA
# rotate data
data <- rotate(data)
# plot data
mean.rn <- mean(data, na.rm=T)
image.plot(data, main=paste("Mean Rn emissions =", sprintf("%.3f", mean.rn)) )
This all looks OK, but I want to be able to plot the data on a lat-long grid. I think I need to convert this array into an sp class object but I don't know how. I know the following (from the web site): "The projection used to project the latitude and longitude coordinates is that used for the Decade of North American Geology (DNAG) maps. The projection type is Spherical Transverse Mercator with a base latitude of zero degrees and a reference longitude of 100 degrees W. The scale factor used is 0.926 with no false easting or northing. The longitude-latitude datum is NAD27 and the units of the xy-coordinates are in meters. The ellipsoid used is Clarke 1866. The resolution of the map is 50x50km". But don't know what to do with this data. I tried:
proj4string(data)=CRS("+init=epsg:4267")
data.sp <- SpatialPoints(data, CRS("+proj=longlat+ellps=clrk66+datum=NAD27") )
But had various problems (with NA's) and fundamentally I think that the data isn't in the right format.. I think that the SpatialPoints function wants a data on location (in 2-D) and a third array of values associated with those locations (x,y,z data - I guess my problem is working out the x and the y's from my data!)
Any help greatly appreciated!
Thanks,
Alex
The file in question is an ASCII raster grid. Coordinates are implicit in this format; a header describes the position of the (usually) lower left corner, as well as the grid dimensions and resolution. After this header section, values separated by white space describe how the variable varies across the grid, with values given in row-major order. Open it in a text editor if you're interested.
You can import such files to R with the fantastic raster package, as follows:
download.file('http://radon.unibas.ch/files/us_rn_50km.zip',
destfile={f <- tempfile()})
unzip(f, exdir=tempdir())
r <- raster(file.path(tempdir(), 'us_rn_50km.txt'))
You can plot it immediately, without assigning the projection:
If you didn't want to transform it to another CRS, you wouldn't necessarily need to assign the current coordinate system. But since you do want to transform it to WGS84 (geographic), you need to first assign the CRS:
proj4string(r) <- '+proj=tmerc +lon_0=-100 +lat_0=0 +k_0=0.926 +datum=NAD27 +ellps=clrk66 +a=6378137 +b=6378137 +units=m +no_defs'
Unfortunately I'm not entirely sure whether this proj4string correctly reflects the info given at the website that provided the data (it would be great if they actually provided the definition in a standard format).
After assigning the CRS, you can project the raster with projectRaster:
r.wgs84 <- projectRaster(r, crs='+init=epsg:4326')
And if you want, write it out to a raster format of your choice, e.g.:
writeRaster(r.wgs84, filename='whatever.tif')

Plotting spatial data when two spatial objects have different CRS

I have a spatial polygon object and a spatial points object. The latter was created from xy latlong data vectors (called latitude and longitude, respectively) in a dataframe, while the former was simply read into R directly using rgdal. My code is as follows:
boros <- readOGR(dsn = ".", "nybb")
rats <- read.csv("nycrats_missing_latlong_removed_4.2.14.csv", header = TRUE)
coordinates(rats) <- ~longitude + latitude
At this point neither spatial object is projected. If I project these objects as follows:
proj4string(boros) <- CRS("+proj=lcc")
proj4string(rats) <- CRS("+proj=lcc")
Both objects are now projected, and both will successfully map with the plot() function as follows:
plot(boros)
plot(rats)
However when I try to plot them together:
plot(boros)
plot(rats, add = TRUE)
I get the first plot only, without the rats object superimposed over boros. However, and this is the big problem, I get NO error message, so I have been unable to determine where the disconnection is between these two spatial objects being able to speak to each other. Both commands run smoothly without error or warning, yet I am left with just the single plot. And when I check the projections of each object with proj4string() I get the same projection returned for each object.
I have now spent many, many hours over several days trying various ways of creating two spatial objects whose CRS and projections match such that they can be mapped together using plot(). Incidentally, one approach I took was to create a shapefile in ArcGIS for the rats object, which worked fine to create the file. But I am still left with the same inability of the two spatial objects to work together in R. I have tried many different projections for both objects, spTransform on both objects, nothing seems to work.
Any help would be most appreciated. I have also included a dropbox link with the 2 data files I have described above:
https://www.dropbox.com/sh/x0urdo6guprnw8y/tQdfzSZ384
So, as some of the comments point out, the problem is that your data and your maps have different projections.
It looks like your map comes from the NYC Department of City Planning. The shapefile is definitely not in WGS84 (longlat), but the CRS is not included in the file (which is very disappointing by the way...). Nevertheless, there is a metadata file which indicates that the shapefile is projected as EPSG 2263.
In order to make use of this in R we need a projection string. The idiomatic way to get this in R is:
library(rgdal)
EPSG <- make_EPSG()
NY <- with(EPSG,EPSG[grepl("New York",note) & code==2263,]$prj4)
NY
# [1] "+proj=lcc +lat_1=41.03333333333333 +lat_2=40.66666666666666 +lat_0=40.16666666666666 +lon_0=-74 +x_0=300000.0000000001 +y_0=0 +datum=NAD83 +units=us-ft +no_defs"
Now we can either take your map and reproject that into WGS84, or take your data and reproject that into the map CRS.
setwd("< directory with all your files >")
data <- read.csv("nycrats_missing_latlong_removed_4.2.14.csv")
# First approach: reproject map into long-lat
wgs.84 <- "+proj=longlat +datum=WGS84"
map <- readOGR(dsn=".",layer="nybb",p4s=NY)
map.wgs84 <- spTransform(map,CRS(wgs.84))
map.wgs84.df <- fortify(map.wgs84)
library(ggplot2)
ggplot(map.wgs84.df, aes(x=long,y=lat,group=group))+
geom_path()+
geom_point(data=data, aes(x=longitude,y=latitude, group=NULL),
colour="red", alpha=0.2, size=1)+
ggtitle("Projection: WGS84 longlat")+
coord_fixed()
# Second approach: reproject data
map.df <- fortify(map)
rats <- SpatialPoints(data[,c("longitude","latitude")],proj4string=CRS(wgs.84))
rats <- spTransform(rats,CRS(NY))
rats.df <- data.frame(coordinates(rats))
ggplot(map.df, aes(x=long,y=lat,group=group))+
geom_path()+
geom_point(data=rats.df, aes(x=longitude,y=latitude, group=NULL),
colour="red", alpha=0.2, size=1)+
ggtitle("Projection: NAD83.2263")+
coord_fixed()
No rats in Central Park?

Resources