Set coordinate reference system to a polygon created in R - r

I am trying to create a zoom-in square(polygon) in a map that is plot using ggplot2::geom_sf()
Therefore, I need the polygon to be a simple feature so I can plot the square and the map together.
I could create the polygon using the following code.
zoom_square_1<- rbind(c(-10.821079,-68.403542),
c(-10.821079,-68.367060),
c(-10.862918,-68.367060),
c(-10.862918,-68.403542),
c(-10.821079,-68.403542)) # add the first point again to it wrap up.
zoom_square_1_pol <- st_polygon(list(zoom_square_1))
plot(zoom_square_1_pol) # it returns the polygon.
However, when I tried to assign a Coordinate reference system (CRS) to it, it does not work. These are the codes I have tried so far.
sp::proj4string(zoom_square_1_pol) <- CRS("+proj=longlat +datum=WGS84 +no_defs")
zoom_square_1_pol_ex1 <- st_as_sf(x = zoom_square_1_pol[[1]],
crs = "+proj=longlat +datum=WGS84 +no_defs")
zoom_square_1_pol_ex2 <- st_transform(x = zoom_square_1_pol,
crs = "+proj=longlat +datum=WGS84 +no_defs")
Any help is welcomed.
After Chris comment, I could actually plot the polygons using ggplot2::geom_sf() and realized that my lat and long coordenates were in the wrong position since the begging. So, this the is final version of the code:
zoom_square_1<- rbind(c(-68.403542,-10.821079),
c(-68.367060,-10.821079),
c(-68.367060,-10.862918),
c(-68.403542,-10.862918),
c(-68.403542,-10.821079)) #add the first point again to it wrap up.
zoom_square_1_pol <- st_polygon(list(zoom_square_1))
zoom_square_1_pol_CRS<- st_sfc(x = zoom_square_1_pol,
crs = "+proj=longlat +datum=WGS84 +no_defs")

I was able to set the crs by feeding the square as a list to st_as_sfc:
res <- st_as_sfc(list(zoom_square_1_pol),
crs = "+proj=longlat +datum=WGS84 +no_defs")

Related

Projecting Rasters, shift to the north. Can i correct it?

I would like to project one raster onto another and while doing so I think the values are changing their position "to the north".
Is this an expected behavior?
I was hoping to create a longlat raster to use it for lookups and GeoJSON generation.
Strangely (or maybe expected, I don't know) resulting GeoJSON positions are shifted (what feels like 10km) to the north.
Do I have a logical mistake somewhere?
This is an example:
x <- raster(ncol=900, nrow=900)
x_proj <- "+proj=stere +lat_0=90 +lat_ts=90 +lon_0=10 +k=0.93301270189 +x_0=0 +y_0=0 +a=6378137 +b=6356752.3142451802 +to_meter=1000 +no_defs "
proj <- CRS(x_proj)
extent(x) <- extent(-523.4622, 376.5378, -4658.645, -3758.645)
projection(x) <- x_proj
x[seq(450,455),seq(1,900)]<-1
new_raster<-raster(ncols=900,nrows=900)
new_raster_crs<- "+proj=longlat +datum=WGS84 +zone=34 +no_defs +ellps=WGS84"
new_raster_proj <- CRS(new_raster_crs)
extent(new_raster) <- extent(3.5889,14.6209, 47.0705, 54.7405)
projection(new_raster) <- new_raster_proj
new_raster<-projectRaster(x,new_raster,method = "bilinear")
Plot of raster x
Plot of Raster new_raster
Is there something I could to with source/dest raster to create a "true" longlat lookup / GeoJSON possibility?
Is there a mistake somewhere ?
Can i maybe change +y_0=0 value to correct this?
If thats the case how can I get the exact value of shift?
Currently I only see the change visually.
That is as expected. Map projections distort (at least one of) shape, size, distance, and direction. In this case, you observe a change in shape.
You do make a mistake here:
new_raster_crs <- "+proj=longlat +datum=WGS84 +zone=34 +no_defs +ellps=WGS84"
"zone" is only relevant for the "UTM" coordinate reference system (and perhaps others), and if you define a datum, you should not also define an ellipsoid. So it should be
new_raster_crs <- "+proj=longlat +datum=WGS84"
But it seems that the other parts you add are simply ignored.
Another mistake is that you still use raster, as it has been replaced by terra. With terra it goes like this:
library(terra)
x <- rast(ncol=900, nrow=900, ext=c(-523.4622, 376.5378, -4658.645, -3758.645),
crs="+proj=stere +lat_0=90 +lat_ts=90 +lon_0=10 +k=0.93301270189 +x_0=0 +y_0=0 +a=6378137 +b=6356752.3142451802 +to_meter=1000 +no_defs")
x[seq(450,455),seq(1,900)]<-1
y <- rast(ncols=900, nrows=900, ext= c(3.5889,14.6209, 47.0705, 54.7405), crs="+proj=longlat +datum=WGS84")
z <- project(x, y)
plot(z)

How to change the projection of a map (created from ETOPO1 bathymetry data) in R

I have downloaded a TIF file from the ETOPO1 website, which contains bathymetry information. I have plotted the bathymetry map using the following code:
bathy <- raster("ice_data.tif")
plot(bathy)
bathy[bathy>0] <-0
dev.new()
plot(bathy)
intervals<-c(-0.000001, -500, -1000, -5000)
colourscale<-colorRampPalette(c("blue","lightblue1"))
plot(bathy, breaks=intervals, col = colourscale(4))
I am wanting to change the project of the map (to this: +proj=laea +lon_0=-21.09375 +lat_0=-90 +datum=WGS84 +units=m +no_defs). I have tried using the code below (with st_transform() function), but am getting an error message
Error in UseMethod("st_transform") : no applicable method for 'st_transform' applied to an object of class "c('RasterLayer', 'Raster', 'BasicRaster')
new_map = st_transform(bathy, crs = "+proj=laea +lon_0=-21.09375 +lat_0=-90 +datum=WGS84 +units=m +no_defs")
Has anyone got any suggestions? It would be very much appreciated!
Thanks
For rasters you need to use the raster::crs() function to change the crs.
The sf::st_transform() function needs an sf object as input.
Try:
new_crs <- "+proj=laea +lon_0=-21.09375 +lat_0=-90 +datum=WGS84 +units=m +no_defs"
crs(bathy) <- new_crs

Plotting a shapefile on a raster layer in R

I want to plot a raster layer with points from a shapefile on top.
I have checked previous answers on this, but i still have a problem.
I can plot the point shapefile and the raster layer separately without problem, but not together.
As far as I can see they should be in same projection and location.
require(maptools)
myproj <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"
shape <- readShapeSpatial("directory/mypoints.shp", proj4string = CRS(myproj))
plot(r <- raster(listVI[200]))
plot(shape)
I found the answer, I will put it here for others who may encounter same problem.
The solution is simply: (as long as raster and shapefile is in same CRS)
plot(r)
plot(shape, add = TRUE)

plot LAT/LON coordinates on geotiff in R

I have a sea ice map as a "geotiff". The eventual goal is to extract sea-ice concentrations at specific lat/lon coordinates.
The geotiff can be found at: http://www.iup.uni-bremen.de:8084/amsr2data/asi_daygrid_swath/n6250/2015/jan/asi-AMSR2-n6250-20150101-v5.tif
What i am trying to do is load the geotiff using raster() and then overlay it by my locations and then using the extract() function to acquire values from the raster file at the specific location.
However my lat/lon points accumulate in the centre of the map. Where do I go wrong? Any help or input is greatly appreciated!
library(raster)
library(sp)
r1 = raster("test.tif")
##check plot
plot(r1)
## check projection
projection(r1)
mydf <- structure(list(longitude = rep(22,7), latitude = seq(60,90,5)),.Names = c("longitude","latitude"), class = "data.frame", row.names = c(NA, -7L))
### Get long and lat from data.frame.
xy <- mydf[,c(1,2)]
spdf <- SpatialPointsDataFrame(coords = xy, data = mydf,
proj4string = CRS("+proj=stere +lat_0=90 +lat_ts=70 +lon_0=-45 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0"))
points(spdf, col="red", lwd=2)
##extract RGB values as reference for sea-ice concentration
seaice_conc = extract(r1, spdf)
Geo-sp's solution would work, but is sub-optimal (slow and imprecise). You should always (re-)project your vector (points in this case) data and not your raster data. Projecting raster data changes values, while this is not the case with vector data. Projecting raster data is also much more computationally intensive.
Thus, you should do something like this:
library(raster)
r <- raster("asi-AMSR2-n6250-20150101-v5.tif")
crs(r)
# CRS arguments:
# +proj=stere +lat_0=90 +lat_ts=70 +lon_0=-45 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0
df <- data.frame(longitude = rep(22,7), latitude = seq(60,90,5), ID=1:7)
spdf <- SpatialPointsDataFrame(coords = df[,1:2], data = df,
proj4string = CRS("+proj=longlat +datum=WGS84"))
library(rgdal)
p <- spTransform(spdf, crs(r))
extract(r, p)
It is important to note that you made a very common mistake:
spdf <- SpatialPointsDataFrame(coords = xy, data = mydf, proj4string =
CRS("+proj=stere +lat_0=90 +lat_ts=70 +lon_0=-45 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m"))
You create a SpatialPointsDataFrame and assign the wrong coordinate reference system (crs). You must assign the crs that actually matches your data, which is "+proj=longlat +datum=WGS84". After that, you can transform the data to the crs that you would like to have (using spTransform).
You can use projectRaster to reproject your raster file. Then you can overlay the points and extract the values.
newproj <- CRS("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +towgs84=0,0,0")
p <- projectRaster(r1, newproj)

Map raw data and mean data based on the shapefile

sI have the dataset (pts) like this:
x <- seq(-124.25,length=115,by=0.5)
y <- seq(26.25,length=46,by=0.5)
z = 1:5290
longlat <- expand.grid(x = x, y = y) # Create an X,Y grid
pts=data.frame(longlat,z)
names(pts) <- c( "x","y","data")
I knew that I can map the dataframe (pts) into a map by doing:
library(sp)
library(rgdal)
library(raster)
library(maps)
coordinates(pts)=~x+y
proj4string(pts)=CRS("+init=epsg:4326") # set it to long, lat
pts = spTransform(pts,CRS(" +init=epsg:4326 +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +towgs84=0,0,0"))
pts <- as(pts, "SpatialPixelsDataFrame")
r = raster(pts)
projection(r) = CRS(" +init=epsg:4326 +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +towgs84=0,0,0")
plot(r)
map("usa",add=T)
Now I would like to create a separate map which shows the means of pts across different regions. The shapefile I want to use is from ftp://ftp.epa.gov/wed/ecoregions/cec_na/NA_CEC_Eco_Level2.zip , however, this is a north america map. How can I create the map showing only US based on this north america map? Or is there another better way to do this? thanks so much.
I think that cutting out the non-US data based on the data in the shapefile alone would be hard, since the regions do not correspond to political boundaries - that could be done with rgeos though.
Assuming that "eco" is a SpatialPolygonsDataFrame read in by rgdal::readOGR or maptools::readShapeSpatial, see the available key data for indexing:
sapply(as.data.frame(eco), function(x) if(!is.numeric(x)) unique(x) else NULL)
If you just want to plot it, set up a map with only the US region to start with and then overplot.
library(maps)
map("usa", col = "transparent")
We see that the data is in Lambert Azimuthal Equal Area:
proj4string(eco)
[1] " +proj=laea +lat_0=45 +lon_0=-100 +x_0=0 +y_0=0 +a=6370997 +b=6370997 +units=m +no_defs"
So
require(rgdal)
eco.laea <- spTransform(eco, CRS("+proj=longlat +ellpse=WGS84"))
plot(eco.laea, add = TRUE)
If you want to plot in the original Lambert Azimuthal Equal Area you'll need to get the bounding box in that projection and start the plot based on that, I just used existing data to make an easy example. I'm pretty sure the data could also be cropped with rgeos against another boundary too, but depends what you actually want.

Resources