5

Fairly novice R user, and I'm sure there's an easy solution for this - but I can't find it. I have a data frame with a series of spatial coordinates, as well as a host of other attributes. Many of the spatial coordinates are the exact same - and I would like to add a set amount of noise to them, so that I can keep them within a certain radius - in this case 0.4 meters, or 40 centimeters while also keeping track of their associated attributes.

I am essentially looking for an R version of this question: https://gis.stackexchange.com/questions/35479/adding-noise-to-overlapping-x-y-coordinates-so-no-longer-in-exact-same-place

... because when I follow the directions for the answer to this question using ArcGIS - I get a series of random points but I lose the attributes associated with those points, and I can't easily find a way to match them back up.

Is there a way to use the jitter function in R or something similar and specify the radius in a spatial context (e.g. 40 cm) that the spatial coordinates are randomly distributed within that range? I don't understand how to manipulate the factor and amount argument in order to get my desired output.

Edit:

Here's an example df with fake coordinates. As you can see the coordinates in the first and third column are the same, because the animal was under the same rock twice. I would like to be able to add jitter to these coordinates so they are slightly different, but I want to control the jitter to be within 40 centimeters (no more than the size of the rock)

mydf <- data.frame("point_id" = 1:6, "date_time" = c("6/5/2018 10:57","6/5/2018 14:30","6/6/2018 10:06","6/6/2018 11:06","6/7/2018 10:35","6/7/2018 15:50"), "Animal_ID" = c(4,5,4,5,4,6), "Rock_ID" = c(1,2,1,3,4,5), x_proj = c(831120.3759,831441.0415,831120.3759,831433.4414,831128.4778,831422.0822), y_proj = c(5877582.998,5875337.074,5877582.998,5875328.897,5877575.360,5875338.216))

#make a separate object for the coordinates#
xy <- mydf[,c(5,6)]

#Convert to a spatialpoints data frame (insert own epsg)
sp.mydf <- SpatialPointsDataFrame(coords = xy, data = tumbling_test, proj4string = CRS("+init=epsg:xxxxx"))

I want my newly generated coordinates to still contain the attribute data from other columns (i.e. Animal_ID, date, etc) because other methods I have used in ArcGIS generate a series of new random pts but I can't match them back to the attributes.

Also if there is a way to only add the jitter to points that have more than one occurrence at a rock, that would be neat. For example here I only need to add the jitter to rows 1 and 3, because the other coordinates do not repeat. Once the jitter is added, I want to convert the results back to a regular dataframe that I will export to a .csv

Brewkeeper
  • 99
  • 9
  • Hi @Brad-Nissen, maybe you could provide an example dataset and specify where exactly are you encountering the problem? – StupidWolf Jan 12 '20 at 19:16
  • @StupidWolf - I didn't even know where to get started here, but based on the answer below, I have successfully jittered the points. Now I simply need to convert the results back to a normal data frame format so I can export it. I can try editing the question to describe my sample data frame nonetheless – Brewkeeper Jan 12 '20 at 21:22

1 Answers1

4

There is, and it is much easier if you're working with an sf object.

You'll need to dig into coordinate reference systems (CRS) a little as well in order to jitter the points the correct distance.

If you're starting with a spatialPointsdataframe, use st_as_sf() to return an sf object.

Below is a reproducible example with points jittered around 5km. The jittering is somewhat random and in this example varies from ~2-5.5 kilometers.

library(sf)
#> Linking to GEOS 3.6.2, GDAL 2.2.3, PROJ 4.9.3
library(tidyverse)

# load example data
nc <- read_sf(system.file('gpkg/nc.gpkg', package = 'sf'))

#make single points from polygons
nc_points <- st_centroid(nc)
#> Warning in st_centroid.sf(nc): st_centroid assumes attributes are constant over
#> geometries of x
#> Warning in st_centroid.sfc(st_geometry(x), of_largest_polygon =
#> of_largest_polygon): st_centroid does not give correct centroids for longitude/
#> latitude data

# Transform to a crs that uses meters as the distance
nc_points <- st_transform(nc_points, 3358)

nc_points_jittered <- st_jitter(nc_points, amount = 5000)

p1 <- ggplot(nc_points) + 
  geom_sf() + 
  ggtitle('Original')

p2 <- ggplot(nc_points_jittered) + 
  geom_sf() + 
  ggtitle('Jittered')

p3 <- ggplot() + 
  geom_sf(data = nc_points, color = 'red') + 
  geom_sf(data = nc_points_jittered, color = 'black') + 
  ggtitle('Both')

cowplot::plot_grid(p1, p2, p3, ncol = 1)

Created on 2020-01-12 by the reprex package (v0.3.0)

mrhellmann
  • 5,069
  • 11
  • 38
  • This worked wonderfully. How do I then convert the resulting jittered points column back into normal columns in the dataframe? Right now it has the heading geometry and each cell is in the form: c(731020.531373004, 3877583.35181795) – Brewkeeper Jan 12 '20 at 21:18
  • Also wondering why the jitter is larger than the amount set? You say it varies up to 5.5 km, is there a way to set a limit on the jitter so it is not larger than the amount? How did you know the amount that it varied in this case? – Brewkeeper Jan 12 '20 at 21:44
  • 1
    @Brewkeeper convert back to coordinates using `st_coordinates()`, check the help file, and it may help to convert back to a lat/lon crs. Spatial data gets a little weird. Lat & lon aren't good enough for many operations. The jitter is kind of by definition 'some amount around this number in any direction'. The code for sf jitter is here: https://github.com/r-spatial/sf/blob/master/R/jitter.R How far are these salamanders running? – mrhellmann Jan 13 '20 at 01:35
  • Thanks! Yeah I converted the data to UTM coordinates before doing the jitter, but I'll look through the help file and convert as needed. These salamanders are hellbenders so they can make big moves if they want to (hundreds of meters if they're inclined) - but most of the time we find them under the same rocks over and over, hence the need for some jitter. How'd you figure out I was tracking salamanders? haha – Brewkeeper Jan 13 '20 at 03:38