R and QGIS: AdehabitatHR: Kernel Homerange size varies in R and later in QGIS - projection mistake? - projection

My code in R:
Brgspat <-SpatialPoints((cbind(Brandgans$lon, Brandgans$lat)),proj4string= CRS( " +proj=longlat + datum=WGS84"))
that means unprojected geographical data
Brgspat <- spTransform(Brgspat,"+init=epsg:25832" )
that means now it is projected.
BrgKernel <- kernelUD(Brgspat, h = "href")
kernel.area(BrgKernel, unout=c("km2"))`
deliveres size of the UD-levels in squarekilometres.
In my data e.g. for UD95: 49.7 km^2.
BrgVolUD <- getvolumeUD(BrgKernel) kernelcontours95 <- getverticeshr(BrgKernel, percent=95) summary (kernelcontours95)
Problem 1: the size of the UD95 differes to that from the kernel.area(...) command. In my data e.g. 5229. WHY is it different?
Further I do:
writeOGR(kernelcontours95, layer ="....", driver= "ESRI Shapefile") in order to export it to QGIS.
In QGIS: My project is also in EPSG25832. When I look in the "project properties" --> "General" it says in Meassurements": "Units for area meassurements" --> "Squaremetres".
Then I use the field calculator with "$area".
Problem 2: The result is a different number again compared to the above numbres. In my data e.g. 522330848 WHY?
I tried it with different projections and unprojected but the results all differ. They should all deliver the same results, shouldn't they?
Help and ideas would greatly be appreciated!

Related

extend (buffer) boundary of shape file in R

I need to extend the boundary of a field (only boundary) by x meters. I tried using gBuffer from rgeos R package - output of the transformation gives me only boundary of the field and rest polygons inside the field are lost with data.
How I can use gBuffer / any other way to extend only boundary of spatial polygon object (shape file) by 10m and keeping everything intact (inside polygons and data)
Tried Code -
field <- raster::shapefile("test.shp")
class(field)
plot(field)
View(field#data)
field <- sp::spTransform(field,CRS("+init=epsg:32632"))
plot(field)
field10m <- rgeos::gBuffer(field , width = 10)
plot(field10m)
Test shapefile can be downloaded from here https://drive.google.com/file/d/1s4NAinDeBow95hxr6gELHHkhwiR3z6Z9/view?usp=sharing
I suggest you consider a workflow based on the {sf} package; it makes for a bit clearer code than sp and rgeos (it will use the same geometry engine, but hide the gritty parts under the hood).
The code preserves all data features (actually, only one - a column named Rx) of your shapefile.
Note that since the yellow element / Rx = 120 / consists of multiple polygons each of them is buffered, resulting in overlaid features. This is expected outcome.
Should this be undesired behavior you can consider using a dplyr::group_by(Rx) followed by dplyr::summarise() to dissolve the internal boundary lines before applying the sf::st_buffer() call.
library(sf)
library(dplyr)
library(mapview) # needed only for the final overview
library(leafsync) # dtto.
test_map <- sf::st_read("./Map/test.shp")
# find an appropriate projected metric CRS
crsuggest::suggest_crs(test_map, type = "projected")
result <- test_map %>%
sf::st_transform(5683) %>% # transform to a metric CRS
sf::st_buffer(10) # buffer by 10 meters
# a visual check / note how the polygons are overlaid
leafsync::latticeview(mapview::mapview(test_map),
mapview::mapview(result))

tmap is plotting a different legend (range of values?) for a cropped rasterlayer compared to original raster

I am extremely new to working with spatial data and so most of what I'm about to say is me trying to speak a foreign language. Right now I am trying to learn how to do this all in R (I am slightly more capable with this data in QGIS but for this solution, I am looking for R only).
My research involves ecological data in Pennsylvania (PA) and so I am playing around with cropping the US NLCD dataset to PA. I have a raster layer for the NLCD and a shapefile for the boundary of Pennsylvania. I am able to successfully crop the larger US raster down to PA as follows:
library(raster)
library(rgdal)
pabound <- readOGR(dsn="...",
layer="PAbound")
nlcdRast <- raster(".../NLCD_2016_Land_Cover_L48_20190424.img")
pabound <- spTransform(pabound,CRS(proj4string(nlcdRast)))
PAnlcd <- raster::crop(nlcdRast,pabound)
If I run the simple plot command for both nlcdRast and PAnlcd (i.e. plot(nlcdRast) they maintain the same color scheme. But when I run it through tmap it seems to look at the cropped data differently and I am not exactly sure how to figure this out. Please see the plots below:
library(tmap)
tm_shape(nlcdRast) +
tm_raster()
And then when I plot the cropped version in tmap:
tm_shape(PAnlcd) +
tm_raster()
As you can see, it is not simply the color palette that is changing (I am confident I could figure that out) but the real problem is I'm losing the important information as seen in the legend. Whereas the full plot actually shows the categorical values for the raster NLCD, the cropped version now seems to show just some unknown numerical range. Even though it looks bad at the moment, I'd like to have the same legend/information as seen in the full US map.
I apologize for not having a more reproducible example but I am completely lost on what is happening here so I can't quite replicate it. I suppose right now I'm just looking for where to look to try and figure out what changed. Thank you in advance.
Cropping is changing the way the pixels are represented. To maintain your values use the stars package (also note I'm using the sf package for the shapefile):
library(stars)
library(sf)
# load in NLCD
nlcdRast <- read_stars(".../NLCD_2016_Land_Cover_L48_20190424.img")
# read in study area
pabound <- st_read(dsn="...", layer="PAbound")
# reproject pabound to match NLCD
pabound <- st_transform(pabound, CRSobj = crs(nlcdRast))
# now crop
panlcd <- st_crop(nlcdRast, pabound)

Plotting error using the ppp function

I am plotting the location of oil refineries in Houston, TX. I defined the study area with the following code.
P4S.latlon <- CRS("+proj=longlat +datum=WGS84 ")
county.lines <-readShapePoly("tl_2017_us_county/tl_2017_us_county.shp", verbose = T, proj4string = P4S.latlon)
harris <- subset(county.lines, county.lines$GEOID == 48201)
brazoria <- subset(county.lines, county.lines$GEOID == 48039)
galveston <- subset(county.lines, county.lines$GEOID == 48167)
chambers <- subset(county.lines, county.lines$GEOID == 48071)
liberty <- subset(county.lines, county.lines$GEOID == 48291)
all.counties <- rbind(harris, brazoria, galveston, chambers, liberty)
ShapePoly <- as(all.counties, "SpatialPolygons")
study.area <- as(ShapePoly, "owin")
Plotting the study area works as intended.
To plot the refinery data I used the following code
refinery <- data.frame(refinery)
attach(refinery)
refinery <- ppp(coords.x1, coords.x2, window = study.area)
The refinery data was originally a shapefile. I converted it to a data frame so I could use ppp().
The issue arising is when I plot refinery there are no points, only shape files.
plot(refinery, pch = 20, col = "firebrick1")
I am writing this script for a class project and usually use ArcGIS for my spatial projects. I'm not sure what could be causing this as I have done extensive research on the ppp function and have replicated this code with a different data set. I would like to have the refineries plotted as points against the county shapefiles.
I can't say for sure since you didn't provide a reproducible example (no link to download data, no loading of R packages used, etc.), but I think this is simply due to the colouring: The argument col controls the colour of the study region (window). To plot the points a given colour use cols, e.g. cols = "firebrick1".
NOTE: You are working directly in lon, lat so your points are really on a sphere (ellipsoid), and very little analysis in R can be done directly for these coordinates (even the plotting is slightly wrong since 1 deg long is different than 1 deg lat). If you continue your analysis you really need to project your coordinates to flat space (use e.g. sf::st_transform() or sp::spTransform()).
When you plot an object of class ppp, the function plot.ppp is executed. The help file for plot.ppp explains that the colours of the points are controlled by the argument cols.

Rasterize error: Polygon to raster conversion produces horizontal lines

I am working with shapefiles in R that I need to convert from polygon to raster. While the vectors look perfect when plotted, when converted to raster using 'rasterize' they produce erroneous horizontal lines. Here is an example of the problem:
Here is a generic example of the code that I am using (sorry that I cannot upload the data itself as it is proprietary):
spdf.dat <- readOGR("directory here", "layer here")
# Plot polygon
plot(spdf.dat, col = 'dimgrey', border = 'black')
# Extract boundaries
ext <- extent(spdf.dat)
# Set resolution for rasterization
res <- 1
# determine no. of columns from extents and resolution
yrow <- round((ext#ymax - ext#ymin) / res)
xcol <- round((ext#xmax - ext#xmin) / res)
# Rasterize base
rast.base <- raster(ext, yrow, xcol, crs = projection(spdf.dat))
# Rasterize substrate polygons
rast <- rasterize(spdf.dat, rast.base, field = 1, fun = 'min', progress='text')
plot(rast, col = 'dimgrey')
Does this seem to be a problem with the source data or the rasterize function? Has anyone seen this sort of error before? Thank you for any advice that you can provide.
To make it official so the question is considered answered, I'll copy my commented responses here. You can therefor accept it.
When I look at your figure, it seems to me that the problematic appearing lines in the raster are situated at the same latitude of some islands. Try to removes these islands from your dataset. If the problem disappear, you'll know that your data is the problem and where in your data the problem lies.
An other option is to try the gdalUtils package which has a function: gdal_rasterize. Maybe gdal is less exigent in the input data.
I had a similar problem rasterizing the TIGER areal water data for the San Juan Islands in Washington State , as well as for Maui - both of these spatial polygon data frames at the default resolution returned by package Tigris using a raster defined by points 1 arc-second of lat/lon apart. There were several horizontal stripes starting at what appeared to be sharp bends of the coastline. Various simplification algorithms helped, but not predictably, and not perfectly.
Try package Velox, which takes some getting used to as it uses Reference Classes. It probably has size limits, as it uses the Boost geometry libraries and works in memory. You don't need to understand it all, I don't. It is fast compared to raster::rasterize (especially for large and complicated spatial lines dataframes), although I didn't experience the hundred-fold speedups claimed, I am not gonna complain about a mere factor of 10 or 20 speedup. Most importantly, velox$rasterize() doesn't leave streaks for the locations I found where raster::rasterize did!
I found that it leaves a lot of memory garbage, and when converting large rasterLayers derived from velox$rasterize, running gc() was helpful before writing the raster in native R .grd format (in INT1S format to save disk space).
Just as a follow up to this question based on my experiences.
The horizontal lines are as a result of these 'islands' as described above. However, it only occurs if the polygon is 'multi-part'. If 'islands' are distinct polygons rather than a separate part of one polygon, then raster:rasterize() works fine.

Distance calculator between the ports

I have a port database which contain nearly 10k port names and its corresponding locations.I want to find the distance between the ports.
Form my understanding using Google distance matrix API, we can only able to find distance between the two points for a set of specific travel modes like bicycle,driving,walking and internal transit.
But In my case I want to find the distance between two ports during the ship voyage. If anyone done Similar sort of work please share your knowledge...
Reference website : [http://www.portworld.com/map]
Thanks!
I was faced with the same problem and found a solution.
1) First you have to create a world map raster with all the parts where a ship can go one value and all the places where it can't go another value.
For this I started with a shape file of all countries borders, added the Suez and Panama canal manually using QGIS. Then I also added the Ice in the Artic.
The rest of the work I did in R using the packages rgdal, raster and gdistance.
install.packages("rgdal")
install.packages("raster")
install.packages("gdistance")
library(rgdal)
library(raster)
library(gdistance)
I first created an empty raster:
new <- raster(ncol=360*5, nrow= 180*5)
projection(new) <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"
(By changing the number of columns you make the raster more precise. When it is low the maps looks like it is build out of dots, while when it is very large it all looks very smooth. The "canals" you draw also disappear when you make the resolution too low. Because they can not be distinguished from the surroundings. However when the calculation time increases very strongly with the resolution of your raster!!)
#Import Shapefile
map <- readOGR(dsn = "location of shape file" , layer = "name shape file")
#Create map from shapefile and empty map
r <- rasterize(map, new)
#replace values to 1 and 99999
values(r)[is.na(values(r))] <- 1
values(r)[values(r)>1] <- 99999
Thus you end up with a map where all places that a ship can go equal to 1 and all places where a ship can't go are 99999.
2) Save the coordinates of the ports in a matrix named "ports". Where the first column are the longitude and the second column the latitude respectively.
Apply the transition needed to calculate the shortest path and apply the geo-correction more info on the geo-correction you can find here.
p <- transition(r, function(x){1/mean(x)}, 8)
p <- geoCorrection(p)
3) Run a loop to calculate the shortest path between all the ports. The length of the shortest paths are stored in a three column matrix called "results".
The whole loop is run in parallel to speed things up.
install.packages("doParallel")
install.packages("foreach")
library(foreach)
library(doParallel)
# Create cluster with number of cores of the system.
cl <- makeCluster(detectCores())
registerDoParallel(cl)
i <- 1
nrow_data <- nrow(ports)
results <- foreach(i=icount(nrow_data), .combine='rbind', .packages="gdistance") %dopar% {
A <- cbind(ports[i,1],ports[i,2])
r <- matrix(NA, ncol=3,nrow=nrow_data)
r[,1] <- i
j <- i+1
while(j<=nrow_data){
r[j,2] <- j
B <- cbind(ports[j,1],ports[j,2])
tryCatch({
path <- shortestPath(p, A,B, output = "SpatialLines")
r[j,3] <- SpatialLinesLengths(path ,longlat=TRUE)
}, error=function(e){})
j <- j+1
}
r[1:nrow_data,]
}
I added the "tryCatch" to eliminate the errors I sometimes received when two ports where located very close to each other. Because of the low resolution of the raster, it can not make a distinction between these two ports.
It is probably not the nicest way to do everything but it works very well for me!

Resources