R: over-write xy coordinates of raster layer - r

I have a raster with XY pixel coordinates which I want to convert to lat and long.
class : RasterLayer
dimensions : 1617, 1596, 2580732 (nrow, ncol, ncell)
resolution : 1, 1 (x, y)
extent : 0, 1596, 0, 1617 (xmin, xmax, ymin, ymax)
coord. ref. : NA
data source : C:\janW1.png
names : janW1
values : 0, 255 (min, max)
I have calculated the lat/long coords using the formula specified here.
This has resulted in the following dataframe
heads(cords)
lat lon x y janW1
1 46.99401 -14.99122 0.5 1616.5 0
2 46.99401 -14.97367 1.5 1616.5 0
3 46.99401 -14.95611 2.5 1616.5 0
4 46.99401 -14.93856 3.5 1616.5 0
5 46.99401 -14.92100 4.5 1616.5 0
6 46.99401 -14.90345 5.5 1616.5 0
How can I over-write or create a duplicate raster with the spatial extent in lat/long instead of image coordinates (XY pixels)? Or is there an easier way to convert the pixels to lat/Lon?
Code
library(raster)
test <- raster('janW1.png')
data_matrix <- rasterToPoints(test)
# Calculate longitude.
lonfract = data_matrix[,"x"] / (1596 - 1)
lon = -15 + (lonfract * (13 - -15))
# Calculate latitude.
latfract = 1.0 - (data_matrix[,"y"] / (1617 - 1))
Ymin = log(tan ((pi/180.0) * (45.0 + (47 / 2.0))))
Ymax = log(tan ((pi/180.0) * (45.0 + (62.999108 / 2.0))))
Yint = Ymin + (latfract * (Ymax - Ymin))
lat = 2.0 * ((180.0/pi) * (atan (exp (Yint))) - 45.0)
# Make single dataframe with XY pixels and latlon coords.
latlon <- data.frame(lat,lon)
tmp <- data.frame(data_matrix)
cords <- cbind(latlon, tmp)
janW1.png

Changing the projection of raster data is not as simple as for points (and lines, polygons). This is because if you compute the new coordinates from the current cells, they won't be in a regular raster.
You can use function projectRaster (raster package) to deal with this.
library(raster)
test <- raster('janW1.png')
# In this case, you need to provide the correct crs to your data
# I am guessing. (this would be necessary for spatial data sets)
crs(test) <- '+proj=merc +datum=WGS84'
# you may also need to set the extent to actual coordinate values
# extent(test) <- c( , , ,)
x <- projectRaster(test, crs='+proj=longlat +datum=WGS84')
Alternatively, you can interpolate values you computed to a new raster. See ?raster::interpolate for examples.

Could you create a raster from scratch with the resolution and spatial extent that you want and then import your values into it. To create a raster you could use something like:
# Create a matrix of coordinates that define the limits of your raster
ex <- matrix(c(-20, -9.5, 20.5, 31.5), nrow = 2, ncol = 2, byrow = T)
# Turn those coordinates into an extent
ex <- extent(ex)
# Create a raster with the same dimensions as your original one
r <- raster(nrows = 1617, ncols = 1596)
# Set the extent of your raster
r <- setExtent(r, ex, keepres=F)
To get the values from your previous raster into the raster you've just created you can use:
test <- raster('janW1.png')
# Create vector of values from test
n <- values(test)
# Give values from test to r
values(r) <- n
I think I got the correct resolution from your code but you will need to put the four coordinates for your extent in yourself. The blank raster will have to have exactly the same resolution as your original raster or it won't work. The blank raster you create is automatically in WGS84 so you might want to reproject it once you've got your data in.

Related

How do you change coordinates of a raster? [duplicate]

I have a raster with XY pixel coordinates which I want to convert to lat and long.
class : RasterLayer
dimensions : 1617, 1596, 2580732 (nrow, ncol, ncell)
resolution : 1, 1 (x, y)
extent : 0, 1596, 0, 1617 (xmin, xmax, ymin, ymax)
coord. ref. : NA
data source : C:\janW1.png
names : janW1
values : 0, 255 (min, max)
I have calculated the lat/long coords using the formula specified here.
This has resulted in the following dataframe
heads(cords)
lat lon x y janW1
1 46.99401 -14.99122 0.5 1616.5 0
2 46.99401 -14.97367 1.5 1616.5 0
3 46.99401 -14.95611 2.5 1616.5 0
4 46.99401 -14.93856 3.5 1616.5 0
5 46.99401 -14.92100 4.5 1616.5 0
6 46.99401 -14.90345 5.5 1616.5 0
How can I over-write or create a duplicate raster with the spatial extent in lat/long instead of image coordinates (XY pixels)? Or is there an easier way to convert the pixels to lat/Lon?
Code
library(raster)
test <- raster('janW1.png')
data_matrix <- rasterToPoints(test)
# Calculate longitude.
lonfract = data_matrix[,"x"] / (1596 - 1)
lon = -15 + (lonfract * (13 - -15))
# Calculate latitude.
latfract = 1.0 - (data_matrix[,"y"] / (1617 - 1))
Ymin = log(tan ((pi/180.0) * (45.0 + (47 / 2.0))))
Ymax = log(tan ((pi/180.0) * (45.0 + (62.999108 / 2.0))))
Yint = Ymin + (latfract * (Ymax - Ymin))
lat = 2.0 * ((180.0/pi) * (atan (exp (Yint))) - 45.0)
# Make single dataframe with XY pixels and latlon coords.
latlon <- data.frame(lat,lon)
tmp <- data.frame(data_matrix)
cords <- cbind(latlon, tmp)
janW1.png
Changing the projection of raster data is not as simple as for points (and lines, polygons). This is because if you compute the new coordinates from the current cells, they won't be in a regular raster.
You can use function projectRaster (raster package) to deal with this.
library(raster)
test <- raster('janW1.png')
# In this case, you need to provide the correct crs to your data
# I am guessing. (this would be necessary for spatial data sets)
crs(test) <- '+proj=merc +datum=WGS84'
# you may also need to set the extent to actual coordinate values
# extent(test) <- c( , , ,)
x <- projectRaster(test, crs='+proj=longlat +datum=WGS84')
Alternatively, you can interpolate values you computed to a new raster. See ?raster::interpolate for examples.
Could you create a raster from scratch with the resolution and spatial extent that you want and then import your values into it. To create a raster you could use something like:
# Create a matrix of coordinates that define the limits of your raster
ex <- matrix(c(-20, -9.5, 20.5, 31.5), nrow = 2, ncol = 2, byrow = T)
# Turn those coordinates into an extent
ex <- extent(ex)
# Create a raster with the same dimensions as your original one
r <- raster(nrows = 1617, ncols = 1596)
# Set the extent of your raster
r <- setExtent(r, ex, keepres=F)
To get the values from your previous raster into the raster you've just created you can use:
test <- raster('janW1.png')
# Create vector of values from test
n <- values(test)
# Give values from test to r
values(r) <- n
I think I got the correct resolution from your code but you will need to put the four coordinates for your extent in yourself. The blank raster will have to have exactly the same resolution as your original raster or it won't work. The blank raster you create is automatically in WGS84 so you might want to reproject it once you've got your data in.

Convert three vectors (lat, lon, value) to raster object in R [duplicate]

I have a data frame in which values (l) are specified for Cartesian coordinates (x, y) as in the following minimal working example.
set.seed(2013)
df <- data.frame( x = rep( 0:1, each=2 ),
y = rep( 0:1, 2),
l = rnorm( 4 ))
df
# x y l
# 1 0 0 -0.09202453
# 2 0 1 0.78901912
# 3 1 0 -0.66744232
# 4 1 1 1.36061149
I want to create a raster using the raster package, but my reading of the documentation has not revealed a simple method for loading data in the form that I have it into the raster cells. I've come up with a couple ways to do it using for loops, but I suspect that there's a much more direct approach that I'm missing.
An easier solution exists as
library(raster)
dfr <- rasterFromXYZ(df) #Convert first two columns as lon-lat and third as value
plot(dfr)
dfr
class : RasterLayer
dimensions : 2, 2, 4 (nrow, ncol, ncell)
resolution : 1, 1 (x, y)
extent : -0.5, 1.5, -0.5, 1.5 (xmin, xmax, ymin, ymax)
coord. ref. : NA
data source : in memory
names : l
values : -2.311813, 0.921186 (min, max)
Further, you may specify the CRS string. Detailed discussion is available here.
Here is one approach, via SpatialPixelsDataFrame
library(raster)
# create spatial points data frame
spg <- df
coordinates(spg) <- ~ x + y
# coerce to SpatialPixelsDataFrame
gridded(spg) <- TRUE
# coerce to raster
rasterDF <- raster(spg)
rasterDF
# class : RasterLayer
# dimensions : 2, 2, 4 (nrow, ncol, ncell)
# resolution : 1, 1 (x, y)
# extent : -0.5, 1.5, -0.5, 1.5 (xmin, xmax, ymin, ymax)
# coord. ref. : NA
# data source : in memory
# names : l
# values : -0.6674423, 1.360611 (min, max)
help('raster') describes a number of methods to create a raster from objects of different classes.
Updating this corresponding to #zubergu about Rasterizing irregular data.
So the answer that I have adapted from the link below and possibly makes it even more simpler to understand is:
library(raster)
library(rasterize)
# Suppose you have a dataframe like this
lon <- runif(20, -180, 180)
lat <- runif(20, -90, 90)
vals <- rnorm(20)
df <- data.frame(lon, lat, vals)
# will need to rename colnames for raster
colnames(df) <- c('x', 'y', 'vals')
# create a raster object
r_obj <- raster(xmn=-180, xmx=180, ymn=-90, ymx=90, resolution=c(5,5))
# use rasterize to create desired raster
r_data <- rasterize(x=df[, 1:2], # lon-lat data
y=r_obj, # raster object
field=df[, 3], # vals to fill raster with
fun=mean) # aggregate function
plot(r_data)
Original response:
for those of you like #yuliaUU looking to convert irregular data to a raster, please see #RobertH's answer here.

How to find the 4 coordinates (lat-long) of a pixel (cell) in a global file?

I am using a climate variable that can be downloaded from here:
ftp://sidads.colorado.edu/pub/DATASETS/nsidc0301_amsre_ease_grid_tbs/global/
This file is a binary (matrix) file with 586 lines and 1383 columns (global map).
I would like to know the 4 coordinates (lat-long) of a pixel (cell)`.
more info about the file :
These data are provided in EASE-Grid projections global cylindricalat 25 km resolution, are two-
byte
Spatial Coordinates:
N: 90° S: -90° E: 180° W: -180°
use the raster package and convert the data to raster objects:
file<- readBin("ID2r1-AMSRE-ML2010001A.v03.06H", integer(), size=2, n=586*1383, signed=T)
m = matrix(data=file,ncol=1383,nrow=586,byrow=TRUE)
r = raster(m, xmn=-180, xmx=180, ymn=-90, ymx=90)
Now the file is a properly spatially referenced object, but without a full specification of the cylindrical projection used you can't get back to lat-long coordinates.
There some more info here http://nsidc.org/data/ease/tools.html including a link to some grids that have the lat-long of grid cells for that grid system:
ftp://sidads.colorado.edu/pub/tools/easegrid/lowres_latlon/
MLLATLSB "latitude"
MLLonLSB "longitude"
so for example we can create a raster of latitude for the cells in your data grid:
> lat <- readBin("MLLATLSB",integer(), size=4, n=586*1383, endian="little")/100000
> latm = matrix(data=lat,ncol=1383,nrow=586,byrow=TRUE)
> latr = raster(latm, xmn=-180, xmx=180, ymn=-90, ymx=90)
and then latr[450,123] is the latitude of cell [450,123] in my data. Repeat with MLLONLSB for longitude.
However this is not sufficient(one lat and long for each pixel) as I would like to compare with ground based measurements so I need to define my region which correspond to this pixel (25 * 25 km or 0.25 degrees). for this purpose I have to know the 4 coordinates (lat-long) of that pixel (cell).
Thanks for any help
EASE GRID uses a Global Cylindrical Equal-Area Projection defined by EPSG 3410, which is metric. As long as I see it, spatial extent should be provided in meters, not geographic coordinates.
From here we see that map extent coordinates are:
xmin: -17609785.303313
ymin: -7389030.516717
xmax: 17698276.686747
ymax: 7300539.133283
So slightly changing your code we have this
library(raster)
library('rgdal')
wdata <- 'D:/Programacao/R/Raster/Stackoverflow'
wshp <- 'S:/Vetor/Administrativo/Portugal'
#setwd(wdata)
file <- readBin(file.path(wdata, "ID2r1-AMSRE-ML2010001D.v03.06H"),
integer(), size=2, n=586 * 1383, signed=T)
m <- matrix(data = file, ncol = 1383, nrow = 586, byrow = TRUE)
-17609785.303313 -7389030.516717 17698276.686747 7300539.133283
rm <- raster(m, xmn = -17609785.303313, xmx = 17698276.686747,
ymn = -7389030.516717, ymx = 7300539.133283)
proj4string(rm) <- CRS('+init=epsg:3410')
> rm
class : RasterLayer
dimensions : 586, 1383, 810438 (nrow, ncol, ncell)
resolution : 25530.05, 25067.53 (x, y)
extent : -17609785, 17698277, -7389031, 7300539 (xmin, xmax, ymin, ymax)
coord. ref. : +init=epsg:3410 +proj=cea +lon_0=0 +lat_ts=30 +x_0=0 +y_0=0 +a=6371228 +b=6371228 +units=m +no_defs
data source : in memory
names : layer
values : 0, 3194 (min, max)
writeRaster(rm, file.path('S:/Temporarios', 'easegrridtest.tif'), overwrite = TRUE)
plot(rm, asp = 1)
We can now overlay some spatial data
afr <- readOGR(dsn = file.path(wdata), layer = 'Africa_final1_dd84')
proj4string(afr) <- CRS('+init=epsg:4326') # Asign projection
afr1 <- spTransform(afr, CRS(proj4string(rm)))
plot(afr1, add = T)
Now you can start playing with extract extent of your ROI, possibly with extent()
I'm not happy with the spatial adjustment. With this approach I got a huge error. I'm not sure about the position error but it is described for this product. Maybe something with the extent parameters.
Since you are interested in use it against ground measures, you could polygonize your ROI and use it in your GPS or GIS.
Also you could get extent of cells of interest with something like:
Choose an aproximate coordinate, identify cell and get the extent:
cell <- cellFromXY(rm, matrix(c('x'= -150000, 'y' =200000), nrow = 1, byrow = T))
r2 <- rasterFromCells(rm, cell, values=TRUE)
extent(r2)
class : Extent
xmin : -172759.8
xmax : -147229.7
ymin : 181362
ymax : 206429.6
And maybe identify a ROI (single cell) in a map (or plot)
cell <- cellFromXY(rm, matrix(c('x'= -1538000, 'y' =1748000), nrow = 1, byrow = T))
r2 <- rasterFromCells(rm, cell, values=TRUE)
r2p <- as(r2, 'SpatialPolygons')
extr2 <- extent(r2) + 300000
plot(rm, col = heat.colors(6), axes = T, ext = extr2)
plot(afr1, add = T, col = 'grey70')
plot(r2p, add = T)
For a particular area
And assuming that by cell you mean column and row values, you could proceed with raster::cellFromRowCol
cell2 <- cellFromRowCol(rm, rownr = mycellnrow, colnr = mycellnrow)
r3 <- rasterFromCells(rm, cell2, values=TRUE)
r3p <- as(r3, 'SpatialPolygons')
extr3 <- extent(r3) + 3000000
In this particular case, 123 and 450 seems to be far from any continental area...
Hope it helps.
More info on AMSR-E/Aqua Daily Gridded Brightness Temperatures here

How to create a raster from a data frame in r?

I have a data frame in which values (l) are specified for Cartesian coordinates (x, y) as in the following minimal working example.
set.seed(2013)
df <- data.frame( x = rep( 0:1, each=2 ),
y = rep( 0:1, 2),
l = rnorm( 4 ))
df
# x y l
# 1 0 0 -0.09202453
# 2 0 1 0.78901912
# 3 1 0 -0.66744232
# 4 1 1 1.36061149
I want to create a raster using the raster package, but my reading of the documentation has not revealed a simple method for loading data in the form that I have it into the raster cells. I've come up with a couple ways to do it using for loops, but I suspect that there's a much more direct approach that I'm missing.
An easier solution exists as
library(raster)
dfr <- rasterFromXYZ(df) #Convert first two columns as lon-lat and third as value
plot(dfr)
dfr
class : RasterLayer
dimensions : 2, 2, 4 (nrow, ncol, ncell)
resolution : 1, 1 (x, y)
extent : -0.5, 1.5, -0.5, 1.5 (xmin, xmax, ymin, ymax)
coord. ref. : NA
data source : in memory
names : l
values : -2.311813, 0.921186 (min, max)
Further, you may specify the CRS string. Detailed discussion is available here.
Here is one approach, via SpatialPixelsDataFrame
library(raster)
# create spatial points data frame
spg <- df
coordinates(spg) <- ~ x + y
# coerce to SpatialPixelsDataFrame
gridded(spg) <- TRUE
# coerce to raster
rasterDF <- raster(spg)
rasterDF
# class : RasterLayer
# dimensions : 2, 2, 4 (nrow, ncol, ncell)
# resolution : 1, 1 (x, y)
# extent : -0.5, 1.5, -0.5, 1.5 (xmin, xmax, ymin, ymax)
# coord. ref. : NA
# data source : in memory
# names : l
# values : -0.6674423, 1.360611 (min, max)
help('raster') describes a number of methods to create a raster from objects of different classes.
Updating this corresponding to #zubergu about Rasterizing irregular data.
So the answer that I have adapted from the link below and possibly makes it even more simpler to understand is:
library(raster)
library(rasterize)
# Suppose you have a dataframe like this
lon <- runif(20, -180, 180)
lat <- runif(20, -90, 90)
vals <- rnorm(20)
df <- data.frame(lon, lat, vals)
# will need to rename colnames for raster
colnames(df) <- c('x', 'y', 'vals')
# create a raster object
r_obj <- raster(xmn=-180, xmx=180, ymn=-90, ymx=90, resolution=c(5,5))
# use rasterize to create desired raster
r_data <- rasterize(x=df[, 1:2], # lon-lat data
y=r_obj, # raster object
field=df[, 3], # vals to fill raster with
fun=mean) # aggregate function
plot(r_data)
Original response:
for those of you like #yuliaUU looking to convert irregular data to a raster, please see #RobertH's answer here.

Crop for SpatialPolygonsDataFrame

I have two SpatialPolygonsDataFrame files: dat1, dat2
extent(dat1)
class : Extent
xmin : -180
xmax : 180
ymin : -90
ymax : 90
extent(dat2)
class : Extent
xmin : -120.0014
xmax : -109.9997
ymin : 48.99944
ymax : 60
I want to crop the file dat1 using the extent of dat2. I don't know how to do it. I just handle raster files using "crop" function before.
When I use this function for my current data, the following error occurs:
> r1 <- crop(BiomassCarbon.shp,alberta.shp)
Error in function (classes, fdef, mtable) :
unable to find an inherited method for function ‘crop’ for signature"SpatialPolygonsDataFrame"’
Streamlined method added 2014-10-9:
raster::crop() can be used to crop Spatial* (as well as Raster*) objects.
For example, here's how you might use it to crop a SpatialPolygons* object:
## Load raster package and an example SpatialPolygonsDataFrame
library(raster)
data("wrld_simpl", package="maptools")
## Crop to the desired extent, then plot
out <- crop(wrld_simpl, extent(130, 180, 40, 70))
plot(out, col="khaki", bg="azure2")
Original (and still functional) answer:
The rgeos function gIntersection() makes this pretty straightforward.
Using mnel's nifty example as a jumping off point:
library(maptools)
library(raster) ## To convert an "Extent" object to a "SpatialPolygons" object.
library(rgeos)
data(wrld_simpl)
## Create the clipping polygon
CP <- as(extent(130, 180, 40, 70), "SpatialPolygons")
proj4string(CP) <- CRS(proj4string(wrld_simpl))
## Clip the map
out <- gIntersection(wrld_simpl, CP, byid=TRUE)
## Plot the output
plot(out, col="khaki", bg="azure2")
Here is an example of how to do this with rgeos using the world map as an example
This comes from Roger Bivand on R-sig-Geo mailing list. Roger is one of the authors of the sp package.
Using the world map as an example
library(maptools)
data(wrld_simpl)
# interested in the arealy bounded by the following rectangle
# rect(130, 40, 180, 70)
library(rgeos)
# create a polygon that defines the boundary
bnds <- cbind(x=c(130, 130, 180, 180, 130), y=c(40, 70, 70, 40, 40))
# convert to a spatial polygons object with the same CRS
SP <- SpatialPolygons(list(Polygons(list(Polygon(bnds)), "1")),
proj4string=CRS(proj4string(wrld_simpl)))
# find the intersection with the original SPDF
gI <- gIntersects(wrld_simpl, SP, byid=TRUE)
# create the new spatial polygons object.
out <- vector(mode="list", length=length(which(gI)))
ii <- 1
for (i in seq(along=gI)) if (gI[i]) {
out[[ii]] <- gIntersection(wrld_simpl[i,], SP)
row.names(out[[ii]]) <- row.names(wrld_simpl)[i]; ii <- ii+1
}
# use rbind.SpatialPolygons method to combine into a new object.
out1 <- do.call("rbind", out)
# look here is Eastern Russia and a bit of Japan and China.
plot(out1, col = "khaki", bg = "azure2")
You cannot use crop on sp polygon objects. You will need to create a polygon representing the bbox coordinates of dat2 and then can use gIntersects in the rgeos library.
Edit: This comment was in relation to the version available in 2012 and this is no longer the case.
see ?crop
corp(x, y, filename="", snap='near', datatype=NULL, ...)
x Raster* object
y Extent object, or any object from which an Extent object can be
extracted (see Details
You need to rasterize the first SpatialPolygon, using rasterize function from the raster package
I create some data to show how to use rasterize:
n <- 1000
x <- runif(n) * 360 - 180
y <- runif(n) * 180 - 90
xy <- cbind(x, y)
vals <- 1:n
p1 <- data.frame(xy, name=vals)
p2 <- data.frame(xy, name=vals)
coordinates(p1) <- ~x+y
coordinates(p2) <- ~x+y
if I try :
crop(p1,p2)
unable to find an inherited method for function ‘crop’ for signature ‘"SpatialPointsDataFrame"’
Now using rasterize
r <- rasterize(p1, r, 'name', fun=min)
crop(r,p2)
class : RasterLayer
dimensions : 18, 36, 648 (nrow, ncol, ncell)
resolution : 10, 10 (x, y)
extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=longlat +datum=WGS84
data source : in memory
names : layer
values : 1, 997 (min, max)

Resources