Unknown CRS in QGIS when projecting to EPSG:25833 in R - r

I want to project a spatial data frame to EPSG 25833 in R but QGIS does not seem to know it (for reproducibility, I use the code jazzurro created in his/her answer to this question with minor changes)
library(rgdal)
mydf <- structure(list(longitude = c(128.6979, 153.0046, 104.3261, 124.9019,
126.7328, 153.2439, 142.8673, 152.689), latitude = c(-7.4197,
-4.7089, -6.7541, 4.7817, 2.1643, -5.65, 23.3882, -5.571)), .Names = c("longitude",
"latitude"), class = "data.frame", row.names = c(NA, -8L))
### Get long and lat from your data.frame. Make sure that the order is in lon/lat.
xy <- mydf[,c(1,2)]
# Here I use the projection EPSG:25833
spdf <- SpatialPointsDataFrame(coords = xy, data = mydf,
proj4string = CRS("+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs"))
#Export as shapefile
writeOGR(spdf, "file location", "proj_test", driver="ESRI Shapefile",overwrite_layer = T) #now I write the subsetted network as a shapefile again
Now when I load the shapefile into QGIS it doesn´t know the projection.
Any ideas?

In making your SpatialPointsDataFrame:
# Wrong!
spdf <- SpatialPointsDataFrame(coords = xy, data = mydf,
proj4string = CRS("+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs"))`
You are telling the data frame what crs your points are in, so you should specify 4326 since your original data is lon/lat.
So it should be:
spdf <- SpatialPointsDataFrame(coords = xy, data = mydf,
proj4string = CRS("+proj=longlat +datum=WGS84"))
And then you can transform the data to another CRS using spTransform:
spTransform(spdf, CRS('+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs'))
For this particular data, we get an error because one of the points doesn't convert to your target CRS:
Error in spTransform(xSP, CRSobj, ...) : failure in points 3 In
addition: Warning message: In spTransform(xSP, CRSobj, ...) : 1
projected point(s) not finite
I prefer working in sf so we could also do:
library(sf)
sfdf <- st_as_sf(mydf, coords = c('longitude', 'latitude'), crs=4326, remove=F)
sfdf_25833 <- sfdf %>% st_transform(25833)
sfdf_25833
#> Simple feature collection with 8 features and 2 fields (with 1 geometry empty)
#> geometry type: POINT
#> dimension: XY
#> bbox: xmin: 5589731 ymin: -19294970 xmax: 11478870 ymax: 19337710
#> epsg (SRID): 25833
#> proj4string: +proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs
#> longitude latitude geometry
#> 1 128.6979 -7.4197 POINT (10198485 -17980649)
#> 2 153.0046 -4.7089 POINT (5636527 -19294974)
#> 3 104.3261 -6.7541 POINT EMPTY
#> 4 124.9019 4.7817 POINT (11478868 18432292)
#> 5 126.7328 2.1643 POINT (11046583 19337712)
#> 6 153.2439 -5.6500 POINT (5589731 -19158700)
#> 7 142.8673 23.3882 POINT (6353660 16093116)
#> 8 152.6890 -5.5710 POINT (5673080 -19163103)
and you can write and open with QGIS using:
write_sf(sfdf_25833, 'mysf.gpkg')

Related

Converting coordinates, radius and site type data from .csv to raster in R

I am having a bit of a problem converting .csv files into raster in R... My .csv file contains coordinates (long and lat) radius (in deg) and site type. I was able to convert the coordinates into raster and was able to plot the circles using st_buffer() but I am facing two problems:
I can't convert the circles into a raster... I tried with rasterize() and fasterize() and both did not work all I'm getting is an empty raster layer
I can't seem to classify the coordinates and circles according to the site type
Any idea of what I might be doing wrong? and how can I classify my circles?
Thank you in advance!
Here is the code I used:
> head(sp_csv_data)
Longitude Latitude Radius Site_Type
1 -177.87567 -24.715167 10 MIG
2 -83.21360 14.401800 1 OBS
3 -82.59392 9.589192 1 NES
4 -82.41060 9.492750 1 NES;BRE
5 -81.17555 7.196750 5 OBS
6 -80.95770 8.852700 1 NES
##Projection systems used
rob_pacific <- "+proj=robin +lon_0=180 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs" # Best to define these first so you don't make mistakes below
longlat <- "+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0"
####Converting to raster####
# Creating a empty raster at 0.5° resolution (you can increase the resolution to get a better border precision)
rs <- raster(ncol = 360*2, nrow = 180*2)
rs[] <- 1:ncell(rs)
crs(rs) <- CRS(longlat)
##Converting to raster
sp_raster <- rasterize(sp_csv_data[,1:2], rs, sp_csv_data[,3])
# Resampling to make sure that it's in the same resolution as sampling area
sp_raster <- resample(sp_raster, rs, resample = "ngb")
#converting into an sf spatial polygon dataframe
sp_raster <- as(sp_raster, "SpatialPolygonsDataFrame")
species_sp <- spTransform(sp_raster, CRS(longlat))
# Define a long & slim polygon that overlaps the meridian line & set its CRS to match that of world
polygon <- st_polygon(x = list(rbind(c(-0.0001, 90),
c(0, 90),
c(0, -90),
c(-0.0001, -90),
c(-0.0001, 90)))) %>%
st_sfc() %>%
st_set_crs(longlat)
# Transform the species distribution polygon object to a Pacific-centred projection polygon object
sp_robinson <- species_sp %>%
st_as_sf() %>%
st_difference(polygon) %>%
st_transform(crs = rob_pacific)
# There is a line in the middle of Antarctica. This is because we have split the map after reprojection. We need to fix this:
bbox1 <- st_bbox(sp_robinson)
bbox1[c(1,3)] <- c(-1e-5,1e-5)
polygon1 <- st_as_sfc(bbox1)
crosses1 <- sp_robinson %>%
st_intersects(polygon1) %>%
sapply(length) %>%
as.logical %>%
which
# Adding buffer 0
sp_robinson[crosses1, ] %<>%
st_buffer(0)
# Adding the circles to the coordinates
sp_robinson2 <- st_buffer(sp_robinson, dist = radius)
> print(sp_robinson2)
Simple feature collection with 143 features and 1 field
geometry type: POLYGON
dimension: XY
bbox: xmin: -17188220 ymin: -5706207 xmax: 17263210 ymax: 6179000
CRS: +proj=robin +lon_0=180 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs
First 10 features:
layer geometry
1 5 POLYGON ((3556791 4766657, ...
2 10 POLYGON ((13713529 4995696,...
3 10 POLYGON ((12834403 4946927,...
4 10 POLYGON ((9991443 4801974, ...
5 5 POLYGON ((4254202 4304190, ...
6 5 POLYGON ((11423719 4327354,...
7 10 POLYGON ((9582710 4282247, ...
8 10 POLYGON ((588877.2 4166512,...
9 5 POLYGON ((4522824 3894919, ...
10 10 POLYGON ((3828685 3886205, ...
sp_robinson3 <- fasterize(sp_robinson2, rs)
> print(sp_robinson3)
class : RasterLayer
dimensions : 360, 720, 259200 (nrow, ncol, ncell)
resolution : 0.5, 0.5 (x, y)
extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
crs : +proj=robin +lon_0=180 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs
source : memory
names : layer
values : NA, NA (min, max)
I want to convert sp_robinson2 into a raster called sp_robinson3 but as you can see both fasterize()and rasterize()are giving me an empty raster layer...
The reason why rasterize does not work in the end is obvious: the crs of the vector and raster do not match. But can you edit your question a bit more to explain what you want to achieve? It is very odd to create a raster and then polygons and then rasterize these again. My impression is that you are making things much more complicated than need be. You also talk about circles. Which circles? I am guessing you may want circles around your points, but that is not what you are doing. It would probably be helpful to figure out things step by step, first figure out how to get the general result you want, then how to get it Pacific centered.
Below is a cleaned up version of the first part of your code. It also makes it reproducible. You need to create example in code, like this:
lon <- c(-177.87567, -83.2136, -82.59392, -82.4106, -81.17555, -80.9577)
lat <- c(-24.715167, 14.4018, 9.589192, 9.49275, 7.19675, 8.8527)
radius <- c(10, 1, 1, 1, 5, 1)
site <- c("MIG", "OBS", "NES", "NES;BRE", "OBS", "NES")
sp_csv_data <- data.frame(lon, lat, radius, site)
## cleaned up projection definitions
rob_pacific <- "+proj=robin +lon_0=180 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs"
longlat <- "+proj=longlat +datum=WGS84"
##Converting to raster
# Creating a empty raster at 0.5° resolution
rs <- raster(res=0.5, crs=lonlat)
values(rs) <- 1:ncell(rs)
sp_raster <- rasterize(sp_csv_data[,1:2], rs, sp_csv_data[,3])
## makes no sense: sp_raster <- resample(sp_raster, rs, resample = "ngb")
#converting into an SpatialPolygonsDataframe
species_sp <- as(sp_raster, "SpatialPolygonsDataFrame")
## makes no sense: species_sp <- spTransform(sp_raster, CRS(longlat))

Creating sf object from dataframe (UTM)

I am new to the sf package in r attempting to create an object from a set of points gives to me in UTM by a collaborator. I've seen how people can use similar methods with lat/long coordinates but have not been able to achieve the same results because of the zone portion of point definitions
can.df <- data.frame(
rbind(
c("NW", "9V", 586518, 7077103),
c("NE", "13W", 645544, 7118728),
c("SW", "11T", 680262, 4865141),
c("SE", "14T", 314095, 497555)),
stringsAsFactors = F)
colnames(can.df) <- c("Corner", "Zone", "Northing", "Easting")
## make xy numeric
num.cols <- c("Northing", "Easting")
can.df[num.cols] <- sapply(can.df[num.cols], as.numeric)
can.df["Zone"] <- as.character(can.df["Zone"])
test <- st_as_sf(can.df,
coords = c("Easting", "Northing", "Zone"),
epsg = 2955)
This will give me the error:
Error in points_cpp(pts, gdim): Not compatible with requested type:
[type=character; target=double].
and if I strip the letters from the zone definition, and use it as numeric. Then I receive:
Error in st_sf(x, ..., agr = agr, sf_column_name = sf_column_name): no
simple features geometry column present
Can anyone shed some light as to what I'm missing?
Try removing "Zone" form coords and change epsg to crs. epsg is not a parameter accepted by st_sf.
library(sf)
#> Linking to GEOS 3.8.0, GDAL 3.0.1, PROJ 6.2.0
can.df <- data.frame(
rbind(
c("NW", "9V", 586518, 7077103),
c("NE", "13W", 645544, 7118728),
c("SW", "11T", 680262, 4865141),
c("SE", "14T", 314095, 497555)),
stringsAsFactors = F)
colnames(can.df) <- c("Corner", "Zone", "Northing", "Easting")
## make xy numeric
num.cols <- c("Northing", "Easting")
can.df[num.cols] <- sapply(can.df[num.cols], as.numeric)
can.df["Zone"] <- as.character(can.df["Zone"])
test <- st_as_sf(can.df,
coords = c("Easting", "Northing", "Zone"),
crs = 2955)
#> Warning in lapply(x[coords], as.numeric): NAs introduced by coercion
#> Error in st_as_sf.data.frame(can.df, coords = c("Easting", "Northing", : missing values in coordinates not allowed
test <- st_as_sf(can.df,
coords = c("Easting", "Northing"),
crs = 2955)
test
#> Simple feature collection with 4 features and 2 fields
#> geometry type: POINT
#> dimension: XY
#> bbox: xmin: 497555 ymin: 314095 xmax: 7118728 ymax: 680262
#> epsg (SRID): 2955
#> proj4string: +proj=utm +zone=11 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs
#> Corner Zone geometry
#> 1 NW c("9V", "13W", "11T", "14T") POINT (7077103 586518)
#> 2 NE c("9V", "13W", "11T", "14T") POINT (7118728 645544)
#> 3 SW c("9V", "13W", "11T", "14T") POINT (4865141 680262)
#> 4 SE c("9V", "13W", "11T", "14T") POINT (497555 314095)
Created on 2019-10-15 by the reprex package (v0.3.0)

Lat/Long Conversion to UTM Loop (R code)

I apologize in advance for my beginner question, but R spatial analysis is completely new to me.
I'm trying to convert an entire dataset (lat,long) into UTM for Ecuador (zone=17). My code below is only converting the first lat/long coordinates. Any advice would be greatly appreciated!
require(proj4)
require(rgdal)
require(sp)
require(proj4)
## Load dataset, total h7_x length = 327463
h7 <- read.csv('h7.csv', header=T)
h7 <- data.frame(x=h7$h7_x, y=h7$h7_y)
## Convert Lat/Long to UTM
proj4string <- "+proj=utm +zone=17 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs"
## Transformed data
pj.h7 <- project(h7, proj4string, inverse=TRUE)
latlon.h7 <- data.frame(lat=pj.h7$y, lon=pj.h7$x)
You can do this:
library(rgdal)
## Load dataset, total h7_x length = 327463
h7 <- read.csv('h7.csv')
coordinates(h7) <- ~ h7_x + h7_y
proj4string(h7) <- CRS("+proj=utm +zone=17 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs")
latlon.h7 <- spTransform(h7, CRS("+proj=longlat +datum=WGS84 +ellps=WGS84"))
And now a reproducible example:
# example data
d <- data.frame(x=c(830816, 848933, 773072), y=c(9933229, 9861005, 9755835), id=1:3)
# create a SpatialPoints object
coordinates(d) <- ~ x + y
proj4string(d) <- CRS("+proj=utm +zone=17 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs")
# transform
latlon <- spTransform(d, CRS("+proj=longlat +datum=WGS84 +ellps=WGS84"))
coords <- coordinates(latlon)

What format should my data be in for a Home Range analysis in adehabitatHR?

I have latlong data of an animal tracked in South Africa and I'm using adehabitatHR for my analysis. Here's a sample of my data:
Latitude Longitude
-25.870265 27.947412
-25.816235 28.022442
-25.751107 28.1113
-25.670537 28.185403
-25.619823 28.290013
I need to transform my data so I can determine home range. I've been using this tutorial to help me and his data looks like it's in decimal degrees too http://www.mikemeredith.net/blog/1212_Data_for_home_range_analysis_in_R.htm
Here's my code:
library(raster)
library(rgdal)
library(maptools)
library(adehabitatHR)
library(sp)
data <- read.csv("stackoverflowEg.csv", sep = ",", header = T)
head(data)
coordinates(data) <- c("X", "Y")
proj4string(data) <- CRS("+init=epsg:4326")
## I got the projected coordinate system from here [http://epsg.io/22235][1]
track <- spTransform(data, CRS("+proj=longlat +init=epsg:22235"))
summary(track)
cp <- mcp(track, percent=95)
cp
The problem is that the resulting value for the mcp is too small (2.230023e-07) so I think I'm doing something wrong with my projections. Any help would be much appreciated.
Try this
coordinates(df) <- ~Longitude+Latitude
proj4string(df) <- CRS('+init=epsg:4326')
dfutm <- spTransform(df, CRS('+init=epsg:32735')) # utm 35S for SAfrica
dfutm
SpatialPoints:
Longitude Latitude
[1,] 594921.4 7138341
[2,] 602485.7 7144268
[3,] 611454.0 7151409
[4,] 618966.7 7160268
[5,] 629521.1 7165787
Coordinate Reference System (CRS) arguments: +init=epsg:32735 +proj=utm +zone=35 +south
+datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0

Convert latitude/longitude to state plane coordinates

I've got a dataset with latitude and longitude which I'd like to convert to the state plane coordinates for Illinois East, using EPSG 2790 (http://spatialreference.org/ref/epsg/2790/) or maybe ESRI 102672 (http://spatialreference.org/ref/esri/102672/).
This has definitely been asked before; my code is based on the answers here ("Non Finite Transformation Detected" in spTransform in rgdal R Package and http://r-sig-geo.2731867.n2.nabble.com/Converting-State-Plane-Coordinates-td5457204.html).
But for some reason I can't get it to work:
library(rgdal)
library(sp)
data = data.frame(long=c(41.20,40.05), lat=c(-86.14,-88.15))
coordinates(data) <- ~ long + lat
proj4string(data) <- CRS("+init=epsg:4326") # latitude/longitude
data.proj <- spTransform(data, CRS("+init=epsg:2790")) # illinois east
Gives:
non finite transformation detected:
long lat
41.20 -86.14 Inf Inf
Error in spTransform(data, CRS("+init=epsg:2790")) : failure in points 1
In addition: Warning message:
In spTransform(data, CRS("+init=epsg:2790")) :
2 projected point(s) not finite
Here's some more working code that clarifies what's going on:
# convert a state-plane coordinate to lat/long
data = data.frame(x=400000,y=0)
coordinates(data) <- ~ x+y
proj4string(data) <- CRS("+init=epsg:2804")
latlong = data.frame(spTransform(data, CRS("+init=epsg:4326")))
setnames(latlong,c("long","lat"))
latlong
gives:
long lat
1 -77 37.66667
and:
# convert a lat/long to state-plane
data = latlong
coordinates(data) <- ~ long+lat
proj4string(data) <- CRS("+init=epsg:4326")
xy = data.frame(spTransform(data, CRS("+init=epsg:2804")))
setnames(xy,c("y","x"))
xy
gives:
> xy
y x
1 4e+05 -2.690839e-08
And here's a function:
# this is for Maryland
lat_long_to_xy = function(lat,long) {
library(rgdal)
library(sp)
data = data.frame(long=long, lat=lat)
coordinates(data) <- ~ long+lat
proj4string(data) <- CRS("+init=epsg:4326")
xy = data.frame(spTransform(data, CRS("+init=epsg:2804")))
setnames(xy,c("y","x"))
return(xy[,c("x","y")])
}
When you set the coordinates for your data, you have to set the latitude before the longitude.
In other words, change:
coordinates(data) <- ~ long + lat
to
coordinates(data) <- ~ lat+long
And it should work.
library(rgdal)
library(sp)
data = data.frame(long=c(41.20,40.05), lat=c(-86.14,-88.15))
coordinates(data) <- ~ lat+long
proj4string(data) <- CRS("+init=epsg:4326")
data.proj <- spTransform(data, CRS("+init=epsg:2790"))
data.proj
Gave me this output:
SpatialPoints:
lat long
[1,] 483979.0 505572.6
[2,] 315643.7 375568.0
Coordinate Reference System (CRS) arguments: +init=epsg:2790 +proj=tmerc
+lat_0=36.66666666666666 +lon_0=-88.33333333333333 +k=0.9999749999999999 +x_0=300000
+y_0=0 +ellps=GRS80 +units=m +no_defs
I had an issue converting in the other direction and found this response on GIS Stack Exchange which may be helpful to future seekers. Depending on whether your coordinate system is NAD83 or NAD83 (HARN), the spatial reference epsg code will differ. If you use the wrong system, it may not be able to convert the point to values beyond the limits of any coordinate plane.
https://gis.stackexchange.com/questions/64654/choosing-the-correct-value-for-proj4string-for-shape-file-reading-in-r-maptools
Reading in lat+long versus long+lat does make a difference in the output- in my case (going from State Plane to WGS84) I had to write
coordinates(data) <- ~ long+lat
You can confirm this by plotting a known reference point to determine if it converted correctly.
The esri code (102649) in rgdal didn't work for me, I had to manually code it in from the proj4js page to go from state plane (0202 Arizona Central) to WGS84:
d<- data.frame(lon=XCord, lat=YCord)
coordinates(d) <- c("lon", "lat")
proj4string(d) <- CRS("+proj=tmerc +lat_0=31 +lon_0=-111.9166666666667 +k=0.9999 +x_0=213360 +y_0=0 +ellps=GRS80 +datum=NAD83 +to_meter=0.3048006096012192 +no_defs")
CRS.new <- CRS("+init=epsg:4326") # WGS 84
d.ch102649 <- spTransform(d, CRS.new)

Resources