Issues plotting spatial point data using tmap - r

I have created a class Large SpatialPointDataFrame from a csv file, and I am trying to plot the data points using tmap. When I plotted the SpatialPointDataFrame using plot(), everything looked fine. However, when I tried to plot it using tmap, it only shows one single point plus it is not where it should be, btw, the point that got shown is the last item in the data frame.
I'm thinking there might be something wrong with my projecton? CRS(Using SVY21 or EPSG:3414) properties of the SpatialPointDataFrame:
crs: +init=epsg:3414 +proj=tmerc +lat_0=1.366666666666667 +lon_0=103.8333333333333 +k=1 +x_0=28001.642 +y_0=38744.572 +ellps=WGS84 +units=m +no_defs
This is how I converted the dataframe to a spatialpointdataframe, where listing is the original dataframe read from a csv file.
coords <- listing[ , c("latitude", "longitude")]
crs <- CRS("+init=epsg:3414")
listing_sp <- SpatialPointsDataFrame(coords = coords, listing, proj4string = crs)
Any suggestions on how I should debug?

In your code, where you have crs <- CRS("+init=epsg:3414"), you are assigning a projection but your source data has not yet been transformed to that projection. If your source data is in lat/lon it's meant to be used with the WGS84 projection (epsg code 4326).
Once you create your spatialPointDataFrame using the projection matching your coordinates, you simply have to reproject using spTransform. To reproject to SVY21, you still need to transform. Can't test without some reproducible data but it should look like this.
coords <- listing[ , c("latitude", "longitude")]
crs <- CRS("+init=epsg:4326")
listing_sp <- SpatialPointsDataFrame(coords = coords, listing, proj4string = crs)
listing_sp_svy21 <- spTransform(listing_sp, CRS("+init=epsg:3414"))

Related

ggplot can find lng and lat in dataset but leaflet cannot, "Need '+proj=longlat +datum=WGS84' "

I have a dataset form the public repo https://github.com/highsource/verbundkarte
Reading the dataset with st_read and plotting it with ggplot yields a beautiful map with correct lng and lat data.
df <- st_read("~/Verkehrsverbunde.shp")
map <- ggplot(df) + geom_sf(aes(fill=SHORTNAME))
I therefore assume, that the lng/lat values are included in the variable df$geometry. However, if I use leaflet, no matter what I try I end up with an error. For instance
df%>% leaflet() %>%
addProviderTiles("CartoDB") %>%
addPolygons(label = htmlEscape(verbunddaten$SHORTNAME)) %>%
setView(lng = 10.3, lat = 51.9, zoom = 5.1)
ends up with
Warning messages:
1: sf layer is not long-lat data
2: sf layer has inconsistent datum (+proj=tmerc +lat_0=0 +lon_0=9 +k=1 +x_0=3500000 +y_0=0 +datum=potsdam +units=m +no_defs ).
Need '+proj=longlat +datum=WGS84'
I found this beautiful conversation of which I understood basically nothing. Reading the data with readOGR as suggested here doesn't solve my problem.
How do I force leaflet to assume the same longlat and EPSG as ggplot?
The data in your Verkehrsverbunde.shp shapefile is in a custom traverse mercator projection, where coordinates are expressed in meters. By contrast, r-leaflet expects data to be expressed in degrees of latitude-longitude, which would look like an equirectangular projection if/when plotted.
I'll guess that, contrary to your belief, ggplot is not using latitude and longitude in degrees, but rather northing and easting values in meters. The representation of the data might look similar for small areas.
In GIS terms, your data is using the EPSG:31467 CRS (Coordinate Reference System), as can be inferred by proj=tmerc and datum=postdam; r-leaflet expects data in the EPSG:4326 CRS.
The approach here would be to reproject your data, so that coordinates are in latitude-longitude as expected. There are plenty of ways to do this; running ogr2ogr -t_srs epsg:4326 Verkehrsverbunde-latlng.shp Verkehrsverbunde-latlng.shp on a command line, using R, or using QGIS, amongst other methods.

Shapefiles do not overlay raster layer in R

I have hundreds of shapefiles without a coordinate reference system. My goal is the overlay the spatial polygons over the WorldClim raster layer. I used this approach before without any problems. However, this time the coordinates from my shapefiles are strange for me. Each coordinate for bounding box and coords within polygons is composed of 8 digit numbers without comma or dot to separate de decimals.
This is the bounding box from one of the shapes:
SHP bbox: xmin:-17367529, xmax:17367529, ymin:-5997367 and ymax:7052489
which are clearly different from the bounding box of the WorldClim raster layer.
WorldClim bbox: xmin=-180,xmax=180,ymin=-60 and ymax=90
When I tried to overlay the shapefile over the raster layer using plot command nothing happens.
plot(shapefile, add=T)
I understood that this is a projection problem. Then I tried to assign the same coordinate system of the WorldClim raster layer in the shapefile using the CRS function. However, the result remains the same (i.e. the shapefiles do not over the raster). In the sequence, I tried to use the spTransform function from the rgdal package to reproject the shapefile coordinates. However, because shapefile does not have any reference system the function does not work and I do not know how to reproject the shapefile in order to match with the raster layer. I've been researching for a few days about how to deal with this problem and I believe that the absence of a reference system is a key point to the problem. However, I'm failing to overcome this problem and I would like to know if someone could help how to deal with this situation.
You need to define the projection of shape files first using proj4string(meuse) or crs(shapefile)<-crs string then you can use spTransform:
library(rgdal)
data(meuse)
coordinates(meuse) <- c("x", "y")
Here you have the spatial data with x and y but you do not have the crs yet! So if you use spTransform it will fail.
summary(meuse) #proj4string : [NA] so below line fails!
meuse.utm <- spTransform(meuse, CRS("+proj=utm +zone=32 +datum=WGS84"))
# Error in spTransform(xSP, CRSobj, ...) :
# No transformation possible from NA reference system
To get around this, as mentioned above, you first need to define the projection as below:
proj4string(meuse) <- CRS(paste("+init=epsg:28992",
"+towgs84=565.237,50.0087,465.658,-0.406857,0.350733,-1.87035,4.0812"))
summary(meuse) #proj4string : epsg:28992... and then you may use spTransform
and then:
meuse.utm <- spTransform(meuse, CRS("+proj=utm +zone=32 +datum=WGS84"))

Create topographic map in R

I am trying to create a script that will generate a 2d topographic or contour map for a given set of coordinates. My goal is something similar to what is produced by
contour(volcano)
but for any location set by the user. This has proved surprisingly challenging! I have tried:
library(elevatr)
library(tidyr)
# Generate a data frame of lat/long coordinates.
ex.df <- data.frame(x=seq(from=-73, to=-71, length.out=10),
y=seq(from=41, to=45, length.out=10))
# Specify projection.
prj_dd <- "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"
# Use elevatr package to get elevation data for each point.
df.sp <- get_elev_point(ex.df, prj = prj_dd, src = "epqs")
# Convert from spatial to regular data frame, remove extra column.
# Use tidyr to convert to lat x lon table with elevation as fill.
# Sorry for the terrible code, I know this is sloppy.
df <- as.data.frame(df.sp)
df$elev_units <- NULL
df.w <- df %>% spread(y, elevation)
df.w <- as.matrix(df.w)
This creates a matrix similar to the volcano dataset but filled with NAs except for the 10 lat/lon pairs with elevation data. contour can handle NAs, but the result of contour(df.w) has only a single tiny line on it. I'm not sure where to go from here. Do I simply need more points? Thanks in advance for any help--I'm pretty new to R and I think I've bitten off more than I can chew with this project.
Sorry for delay in responding. I suppose I need to check SO for elevatr questions!
I would use elevatr::get_elev_raster(), which returns a raster object which can be plotted directly with raster::contour().
Code example below grabs a smaller area and at a pretty coarse resolution. Resultant contour looks decent though.
library(elevatr)
library(raster)
# Generate a data frame of lat/long coordinates.
ex.df <- data.frame(x=seq(from=-73, to=-72.5, length.out=10),
y=seq(from=41, to=41.5, length.out=10))
# Specify projection.
prj_dd <- "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"
# Use elevatr package to get elevation data for each point.
elev <- get_elev_raster(ex.df, prj = prj_dd, z = 10, clip = "bbox")
raster::contour(elev)
If it is a requirement to use graphic::contour(), you'll need to convert the raster object to a matrix first with raster::as.matrix(elev). That flips the coords though and I haven't spent enough time to try and get that part figured out... Hopefully the raster solution works for you.

r - match spatial projections of spatial objects and overlay plots

I am trying to overlay 2 spatial objects using the plot() function. I understand that the projections of the 2 objects (of class SpatialLinesDataFrame and SpatialPolygonsDataFrame) need to be the same in order to have them visualized in the same plot. I've found similar questions here and here, but none of these can help me what I want to achieve.
Here's the coding for the SpatialPolygonsDataFrame. (v.map is a list of .kml files and loccoor is an object that stores location and corresponding x and y coordinates):
map.l<-list()
for (i in 1:length(v.map)){
ll<-ogrListLayers(paste(loccoor,"/",v.map[i],".kml",sep=""))
shp<-readOGR(paste(loccoor,"/",v.map[i],".kml",sep=""),layer=ll)
map<-spTransform(shp, CRS("+proj=longlat +datum=WGS84"))
map.l[[i]]<-map
}
plot(map.l[[1]],xlim=c(min(coor[,3]),max(coor[,3])),
ylim=c(min(coor[,2]),max(coor[,2])))
for (i in 2:length(v.map)){
plot(map.l[[i]],xlim=c(min(coor[,3]),max(coor[,3])),
ylim=c(min(coor[,2]),max(coor[,2])),add=T)
}
projection SpatialPolygonsDataFrame "map": "+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0"
projection SpatialLinesDataFrame "contours": "+proj=aeqd +ellps=WGS84 +lon_0=-XX.XXXXX +lat_0=XX.XXXXX".
I want to transform the projection of the "map" object to match that of the "contours". Simply replacing the "CRS("+proj=longlat +datum=WGS84")" of the "map" object with the projection of the "contours" object doesn't seem to work, because then the polygons are no longer plotted (visible).
Any thoughts to this would be greatly appreciated!
Here's a not very great metaphor: The coordinates are like directions, and the crs tells us what language the directions are in. So, if you change the crs, but you leave the coordinates as they are, then it would be like trying to read German directions with a Spanish dictionary.
We can translate the directions from one crs to another using sp::spTransform().
The function takes two arguments: a spatial object, and a crs.
We can use raster::crs() to get the crs from the another spatial object. So, to transform the map's coordinates (and crs) to the crs of the contours:
map <- spTransform(map, crs(contours))

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)

Resources