How to write new shapefiles from exisiting GPS coordinates in R? - r

I am a novice with R maps and I would like to graphically display plant species distributions as polygons on a map. I have a csv file of UTM coordinates. I am using the maps and maptools programs in R and I have been able to read in existing ESRI shapefiles. The discussion posts that I have seen all seem to deal with reading in existing shapefiles and editing them somewhat and "rewriting" them back out. Is there a simple way to convert my csv file into a shapefile for mapping purposes? Thank you for your help, Eric

You should have more info about your coordinate reference system. And I'm not sure about what you mean with 'polygon' : i think that .csv can only contain coordinates points.
Here is an exemple of workflow : create a simple data.frame; set coordinates ; write shapefile ; read shapefile back; and plot simple map. Hope it helps. Instead of creating a data.frame, you could juste import your .csv.
# Load libraries
library(sp)
library(rgdal)
# set CRS . For epsg code, see http://spatialreference.org/
projTest<-CRS("+init=epsg:28992")
# create a temp dir for shapefiles
trashMap<-tempdir()
# create dumb data:
occData<-data.frame(x=c(12,13,14,20),y=c(0,1,4,9),obs=c("a","b","c","d"))
# set x and y as coordinates
coordinates(occData)<-c('x','y')
# assign CRS
proj4string(occData)<-projTest
# write simple shapefile in trashMap dir
writeOGR(occData, trashMap, layer='testLayer', driver="ESRI Shapefile")
# get list of Layers
layers<-ogrListLayers(trashMap)
# read shapefile and selected layer
occData2<-readOGR(trashMap, layers)
# Modify data
occData2$newColumn<-c('no','stress','','dude')
occData2
# verify that is projected
is.projected(occData2)
# display projection type
proj4string(occData2)
# print maps before and after export in shapefile.
print(spplot(occData, auto.key=F, col.regions='black', scales=list(draw=T), pch=2, cex=1))
print(spplot(occData2, auto.key=F, col.regions='black', scales=list(draw=T), pch=2, cex=1))

Related

How do I get my coordinate points to be in my spatial dataframe so it puts the points in the right place when I upload it to ArcGIS as a shapefile?

I'm trying to upload some of my analysis from R into ArcGIS but there isn't any coordinate points when I upload it. In my original CSV file I had coordinate points but lose them when I create a spatial dataframe???
#read csv file into r and then omit all the NAs
all_baboon <- read.csv(file = 'All_GPS_Collar_Data.csv')
baboon_GPS <- na.omit(all_baboon)
#create spatial dataframe by first creating new table with just individuals and x y coordinates
baboon.sp <- baboon_GPS[, c("Baboon", "X","Y")]
#create spatial points data frame
coordinates(baboon.sp) <- c("X", "Y")
str(baboon.sp)
#set coordinate referene system
proj4string(baboon.sp) <- CRS( "+proj=utm + zone=37 + datum=WGS84 +units=m +no_defs")
#calculate MCPs for each social group, 100% of points used in this scenario
baboon.mcp <- mcp(baboon.sp, percent=100)
baboon.mcp
I followed a tutorial for using adehabitat to find the home range of baboons. I can plot the home ranges in R, but haven't put a map down as the background because I want to import it as a shapefile into arcGIS. However, when I created a shapefile, theres no coordinates so the points and polygons don't get placed on the map.
shapefile(x = baboon.mcp, file = ".../baboonmcp.shp")
writeOGR(baboon.mcp, dsn = "...file_location", layer = "baboon.mcp", driver = "ESRI Shapefile")
I've tried it using shapefile and writeOGR but still have nothing. How can I add back the coordinates from the original csv file so it can be plotted in arcGIS?
Maybe the problem come from writeOGR, see writeOGR, read OGR does not provide X Y coordinates, which I need after clipping shapefile in R It's maybe better to use writeSpatialShape from the maptools package, you can try.

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"))

Plotting map points in R

I have successfully loaded a shapefile of NYC PUMA areas into R with maptools and I want to plot 55 points on top of it that I have in another file as follows:
X Y pumace10 events_2008 events_2009
-73.9092456917 40.8916125162 3701 2 0
-73.8617096298 40.8899373255 3702 0 0
-73.8010284966 40.8460832277 3703 1 1
However, the points will not plot.
First I do this to plot the shapefile:
plot(nycs)
And it plots the shapefile
Then I try to plot the points on top but no matter which of the following I do it always fails:
points(nyc_data$X,nnyc_data$Y,pch=20,col="red")
or
plot(nyc_data, pch=16, col='firebrick',add=TRUE)
or
plot(nyc_data$X,nyc_data$Y,pch=20,col="red")
(that final one plots the data on a new plot that is just an X-Y scatter instead of overlaid on the shapefile)
Any ideas how to do this?
EDIT, files added (amended to working files, hopefully!):
Shapefile info: https://www.sendspace.com/file/wbqrpb
Points file: https://www.sendspace.com/file/9yrrbu
Anyway you could send the files you are using?
My guess is that you have one of two problems:
1) either the "points" spatial data frame or the NYC PUMA file do not have a coordinate reference system.
2) they both have reference systems, but they are different.
Likely, your problem is that the points lack a reference system.
EDIT:
The problem is that the two datasets are in different coordinates, and I'm not sure what the coordinate system for the points is. Here is my code. The problem is that the CRS for the points is clearly neither regular lat/long nor the projection used in the shapefile. If you have more info on the source of the data points maybe we can see what projection they use.
library(sp)
library(maptools)
library(rgdal)
library(rgeos)
Points=read.csv("nyc_data_sample.csv",stringsAsFactors=F)
shapefile=readOGR("shapefiles","nyu_2451_34512")
Points_Shape = SpatialPoints(Points[,c("X","Y")],proj4string=CRS("+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0"))
#Points_Shape = SpatialPoints(Points[,c("X","Y")],proj4string=CRS(proj4string(shapefile)))
Points_Shape = SpatialPointsDataFrame(Points_Shape,Points)

Assigning spatial coordinates to an array in R

I have downloaded a text file of data from the following link: http://radon.unibas.ch/files/us_rn_50km.zip
After unzipping I use the following lines of code to plot up the data:
# load libraries
library(fields)
# function to rotate a matrix (and transpose)
rotate <- function(x) t(apply(x, 2, rev))
# read data
data <- as.matrix(read.table("~/Downloads/us_rn_50km.txt", skip=6))
data[data<=0] <- NA
# rotate data
data <- rotate(data)
# plot data
mean.rn <- mean(data, na.rm=T)
image.plot(data, main=paste("Mean Rn emissions =", sprintf("%.3f", mean.rn)) )
This all looks OK, but I want to be able to plot the data on a lat-long grid. I think I need to convert this array into an sp class object but I don't know how. I know the following (from the web site): "The projection used to project the latitude and longitude coordinates is that used for the Decade of North American Geology (DNAG) maps. The projection type is Spherical Transverse Mercator with a base latitude of zero degrees and a reference longitude of 100 degrees W. The scale factor used is 0.926 with no false easting or northing. The longitude-latitude datum is NAD27 and the units of the xy-coordinates are in meters. The ellipsoid used is Clarke 1866. The resolution of the map is 50x50km". But don't know what to do with this data. I tried:
proj4string(data)=CRS("+init=epsg:4267")
data.sp <- SpatialPoints(data, CRS("+proj=longlat+ellps=clrk66+datum=NAD27") )
But had various problems (with NA's) and fundamentally I think that the data isn't in the right format.. I think that the SpatialPoints function wants a data on location (in 2-D) and a third array of values associated with those locations (x,y,z data - I guess my problem is working out the x and the y's from my data!)
Any help greatly appreciated!
Thanks,
Alex
The file in question is an ASCII raster grid. Coordinates are implicit in this format; a header describes the position of the (usually) lower left corner, as well as the grid dimensions and resolution. After this header section, values separated by white space describe how the variable varies across the grid, with values given in row-major order. Open it in a text editor if you're interested.
You can import such files to R with the fantastic raster package, as follows:
download.file('http://radon.unibas.ch/files/us_rn_50km.zip',
destfile={f <- tempfile()})
unzip(f, exdir=tempdir())
r <- raster(file.path(tempdir(), 'us_rn_50km.txt'))
You can plot it immediately, without assigning the projection:
If you didn't want to transform it to another CRS, you wouldn't necessarily need to assign the current coordinate system. But since you do want to transform it to WGS84 (geographic), you need to first assign the CRS:
proj4string(r) <- '+proj=tmerc +lon_0=-100 +lat_0=0 +k_0=0.926 +datum=NAD27 +ellps=clrk66 +a=6378137 +b=6378137 +units=m +no_defs'
Unfortunately I'm not entirely sure whether this proj4string correctly reflects the info given at the website that provided the data (it would be great if they actually provided the definition in a standard format).
After assigning the CRS, you can project the raster with projectRaster:
r.wgs84 <- projectRaster(r, crs='+init=epsg:4326')
And if you want, write it out to a raster format of your choice, e.g.:
writeRaster(r.wgs84, filename='whatever.tif')

How to create a KML file using R

I have written a R script to get some map point data (Latitude and Longitude values). I am able to plot them in R and visualize them. But now I want to generate a KML file from this data and view using Google Earth. So that I can share it with colleagues and they can see it on Google Earth too.
What is the best method / package to do this ?
Check the writeOGR function in the rgdal package. Here is a simple example:
library("sp")
library("rgdal")
data(meuse)
coordinates(meuse) <- c("x", "y")
proj4string(meuse) <- CRS("+init=epsg:28992")
meuse_ll <- spTransform(meuse, CRS("+proj=longlat +datum=WGS84"))
writeOGR(meuse_ll["zinc"], "meuse.kml", layer="zinc", driver="KML")
The objects exported are SpatialPointsDataFrame, SpatialLinesDataFrame, or SpatialPolygonsDataFrame objects as defined in the sp package.
R> class(meuse)
[1] "SpatialPointsDataFrame"
attr(,"package")
[1] "sp"
For writing with the KML driver, note that the geometries should be in geographical coordinates with datum WGS84.
I think is worth mentioning the plotKML package as well.
Edit 2022-05-16: Seems that plotKML is no longer on CRAN, but you can use an older package version from the CRAN archive. See Installing a Package Removed from CRAN.
However, for easy sharing among colleagues I found interesting the mapview package based on leaflet package. One can save a map as HTML document with various options for a background map; no need of Google Earth and the HTML map will run on your browser.
Some examples:
library(sp)
library(rgdal)
library(raster)
library(plotKML)
library(mapview)
# A SpatialPointsDataFrame example
data(meuse)
coordinates(meuse) <- ~x+y
proj4string(meuse) <- CRS("+init=epsg:28992") # CRS Amersfoort (Netherlands)
# make a KML file from SpatialPointsDataFrame object
# will get a warning like "Reprojecting to +proj=longlat +datum=WGS84 ..."
# as it is expected to work with geographical coordinates with datum=WGS84,
# but seems that it takes care of the reprojecting.
plotKML::kml(meuse,
file.name = "meuse_cadium.kml",
points_names = meuse$cadmium,
colour = "#FF0000",
alpha = 0.6,
size = 1,
shape = "http://maps.google.com/mapfiles/kml/pal2/icon18.png")
# Or, an easy to make interactive map with mapView()
mapView(meuse)
# A RasterLayer example
data(meuse.grid)
gridded(meuse.grid) <- ~x+y
proj4string(meuse.grid) <- CRS("+init=epsg:28992")
dist_rst <- raster(meuse.grid["dist"])
# make a KML file from RasterLayer object
plotKML::kml(dist_rst,
file.name = "dist_rst.kml",
colour_scale = SAGA_pal[[1]])
# Or, easy to make interactive map with mapView() - display raster and add the points
mapView(dist_rst, legend=TRUE) + meuse
# However, note that for bigger raster datasets mapView() might reduce from resolution
More examples with plotKML here.
For mapview, an intro can be found here.
If you're willing to step outside R, there is a free program called DNRGarmin can take a comma separated file as a .txt and convert it to .kml for import into google earth.
You can find it here:
http://www.dnr.state.mn.us/mis/gis/tools/arcview/extensions/DNRGarmin/DNRGarmin.html
so in R:
my.geo.data <- all.my.data[ c("unique.id", "lats", "longs")]
write.csv( my.geo.data, file = "myGeoData.txt")
open DNRGarmin,
File -> Load From -> File -> myGeoData.txt Then,
File -> Save to -> File -> myGeoData.kml
#rcs's advice re: WGS84 applies for this answer too.
Good luck
If you/your collegues know QGIS, this is a very good way to display data in Google Earth. QGIS has the feature of showing Google Earth as a base map and then you can open your spatial data and it will be displayed on the base map. Of course it requires your data to be correctly projected as rcs says.
Here you need to export your points as a shape file using the maptools package and Spatial Points package:
library(maptools)
library(sp)
## define projection
myProjection <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"
## your points in format dataframe
coordinates.df <- as.data.frame(MyCoordinates)
## the number of points you have as dataframe
number <- as.data.frame(NumberOfPoints)
## convert points to Spatial Points Dataframe
myPoints.spdf <- SpatialPointsDataFrame(coordinates.df, number, proj4string = CRS(myProjection))
## save shapefile
writeSpatialShape(myPoints.spdf, "MyPointsName")
Your points can now be opened in QGIS and be displayed in Google Earth. In QGIS your data can also easily be saved as kmz file if necessary.

Resources