Map raw data and mean data based on the shapefile - r

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.

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)

R - transition function for modelling surface water flow with gdistance

I am trying to model overland (surface) water flow from specified origin points to a single downslope goal point using the gdistance shortestPath function. I need help with defining the appropriate transitionFunction for this, as I need to make sure the least cost path only allows water to flow along the path to elevation cells of equal or lesser value than the previous cell. The transitionFunction in the example below selects the minimum elevation cell but, based on the transitionFunction I have defined, this value may still be greater than the previous cell value.
I realize that, when the above is defined as I want it, the path may terminate before reaching the goal point. This is fine, although I would ideally like to be able to preserve the path from the origin to wherever it terminates if possible.
Also, if anyone knows of a different R package capable of modelling this kind of thing, please let me know.
library(gdistance)
library(raster)
library(elevatr)
library(sp)
#load example DEM raster
data(lake)
elevation <- get_elev_raster(lake, z = 9)
#remove negative elevation values from raster
elevation[elevation < 0] <- NA
#create origin and goal points with same projection as elevation raster
origin <- SpatialPoints(cbind(1790000, 640000), proj4string = CRS("+proj=aea +lat_1=20 +lat_2=60 +lat_0=40 +lon_0=-96 +x_0=0 +y_0=0 +datum=NAD83 +units=m +no_defs +ellps=GRS80 +towgs84=0,0,0"))
goal <- SpatialPoints(cbind(1820000, 540000), proj4string = CRS("+proj=aea +lat_1=20 +lat_2=60 +lat_0=40 +lon_0=-96 +x_0=0 +y_0=0 +datum=NAD83 +units=m +no_defs +ellps=GRS80 +towgs84=0,0,0"))
#create df data and convert to SpatialPointsDataFrame
odf <- data.frame("flowreg" = 1)
gdf <- data.frame("flowreg" = 2)
origindf <- SpatialPointsDataFrame(origin, odf)
goaldf <- SpatialPointsDataFrame(goal, gdf)
trCost1 <- transition(elevation, transitionFunction=function(x) 1/min(x), directions=8)
trCost1gc <- geoCorrection(trCost1, type="c")
plot(raster(trCost1))
sPath1 <- shortestPath(trCost1, origin, goal,
output="SpatialLines")
plot(elevation)
plot(origindf, add = TRUE, col='red', cex = 5)
plot(goaldf, add = TRUE, col='green', cex = 5)
lines(sPath1)
I have found the GRASS GIS (accessed in R using rgrass7) r.drain function OR raster::flowPath achieve what I am trying to do in the above question.

Set coordinate reference system to a polygon created in 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")

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)

How to calculate polygon means and map them?

I 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)
my question is that how I can calculate the means of the 10 EPA Regions and map the means?
the EPA regions can be found at the bottom of the webpage at
http://www.epa.gov/wed/pages/ecoregions/level_iii_iv.htm
Thanks
First read the shape file
er <- readOGR("Eco_Level_III_US.shp", "Eco_Level_III_US")
Then make sure ther raster r and the ecoregions er have the same projection
er.4326 <- spTransform(er, CRS("+init=epsg:4326 +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +towgs84=0,0,0"))
Extract the r raster data from the shapefile (that may take a few minutes), calculate the mean and add it to your polyongs.
er.v <- extract(r, er.4326)
means <- sapply(er.v, mean)
er.4326$means <- means
And finally plot it
spplot(er.4326, "means")

Resources