Search code examples
rplotsubsetextractscatter

Spatial subset of data frame in R


I have a big data frame that I plotted using plot(). I then used:

library(splancs) 

polygon_xy = getpoly(quiet=FALSE) 

and drew points on the plot to select my area of interest. This generated the x,y coordinates of the polygon I drew.

I want to extract the data that sits inside the polygon, or to subset my df to include only the points that sit inside the polygon. Any suggestions how to do that?


Solution

  • The point data needs to be in a specific format (i.e., a matrix with x and y) when you use plot and for getpoly to recognize the coordinates.

    library(splancs)
    library(tidyverse)
    library(sf)
    
    set.seed(543)
    xy <-
      cbind(x = runif(n = 25, min = -118, max = -117),
            y = runif(n = 25, min = 40, max = 42))
    
    plot(xy)
    
    # Draw a polygon for study area.
    poly <- getpoly()
    
    # Convert to sf objects.
    polysf <- st_as_sf(as.data.frame(poly), coords = c("V1", "V2"), crs = 4326) %>% 
      dplyr::summarise() %>%
      st_cast("POLYGON") %>% 
      st_convex_hull()
    
    xysf <- st_as_sf(as.data.frame(xy), coords = c("x", "y"), crs = 4326)
    
    # Do an intersection to keep only points inside the drawn polygon.
    xy_intersect <- st_intersection(polysf, xysf)
    

    Output

    Simple feature collection with 9 features and 0 fields
    Geometry type: POINT
    Dimension:     XY
    Bounding box:  xmin: -117.7913 ymin: 40.82405 xmax: -117.4264 ymax: 41.7448
    Geodetic CRS:  WGS 84
                        geometry
    1 POINT (-117.4264 41.18712)
    2  POINT (-117.5756 41.7448)
    3 POINT (-117.7913 40.82405)
    4 POINT (-117.7032 41.15077)
    5 POINT (-117.5634 41.23936)
    6 POINT (-117.7441 40.84163)
    7  POINT (-117.692 41.27514)
    8 POINT (-117.6864 40.98462)
    9 POINT (-117.5759 40.88477)
    

    Plotted with mapview::mapview(xy_intersect) from library(mapview)

    enter image description here

    However, if you want to extract rows from your original dataframe, then here is another hack for extracting the points that fall within a drawn polygon (when the polygon coordinates look like 0.003456 for example).

    library(splancs)
    library(tidyverse)
    
    set.seed(543)
    xy <-
      cbind(x = runif(n = 25, min = -118, max = -117),
            y = runif(n = 25, min = 40, max = 42))
    
    plot(xy)
    
    # Draw a polygon for study area.
    poly <- getpoly()
    
    # Plot the results.
    plot(xy)
    polygon(poly)
    
    # This will return a logical vector for points in the polygon
    io <- inout(xy, poly)
    points(xy[io,], pch = 16, col = "blue")
    
    # Then, can use the index from io to extract the points that 
    # are inside the polygon from the original set of points.
    extract_points <- as.data.frame(xy)[which(io == TRUE),]
    
    extract_points
    

    Output

               x        y
    2  -117.4506 41.17794
    3  -117.4829 40.71030
    8  -117.4679 40.71702
    19 -117.3354 40.53687
    21 -117.5219 40.47077
    22 -117.4876 40.18188
    25 -117.2015 40.86243
    

    enter image description here