I have Global Fishing Watch data for the whole world in a dataframe with columns being Lon, Lat, fishing_hours, gear type.

How do I crop the data to my area of interest?

I have tried the following:

# project fishing data
coordinates(fishing_data) = ~ Lon+Lat # this creates a SpatialPointsDataFrame which will create a KDE for each id.
crs <-"+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"
proj4string(fishing_data) <- crs

# create clipping polygon with extent being the study area
cp <- as(extent(-70, -55, -60, -38), "SpatialPolygons")
crs <-"+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"
proj4string(cp) <- crs

# clip fishing data by clipping polygon
dfc <- gIntersection(df2, cp, byid=TRUE) 

However, this takes a very long time to run and / or R crashes.

I do not have any sample data. I do not know how to create MRE for spatial data.

2 Answers 2


I would recommend modernizing your workflow a bit. The depreciation schedule for sp and rgdal have been announced, being replaced by sf. The terra library is the replacement for raster, with much of the processing now occurring in C++. This is all somewhat forcing migration to the new spatial classes in sf and terra. Honestly, they are much faster with modernized code.

First, add libraries and create some dummy data that looks like yours.


fishing_pts = data.frame(lon=runif(100,-80,-50), lat=runif(100,-60,-40))
  fishing_pts <- st_as_sf(fishing_pts, coords = c("lon", "lat"), 
                          crs = 4326, agr = "constant")

Here we can use the terra crop approach. However please note that, to work your vector data needs to be a terra vect class object. This can be done easily on-the-fly within crop using vect. We wrap it all in st_as_sf to coerce back to an sf object. The crop function clips the data to a terra extent object, passed in the function using ext.

fishing_pts_sub <- st_as_sf(crop(vect(fishing_pts), 
                         ext(-70, -55, -60, -38)))
  plot(fishing_pts_sub, pch=20, add=TRUE)

Here is an approach staying entirely in sf using st_intersects. Note that the input into the st_bbox function are in a different order than raster::extent or terra::ext (sf::st_bbox=xmin, ymin, xmax, ymax verses terra::ext=xmin, xmax, ymin, ymax). First we create an extent polygon using st_bbox, st_as_sfc coerces to a polygon object, then we clip the data with st_intersection.

e <- st_as_sfc(st_bbox(c(xmin = -70, xmax = -55, 
               ymax = -38, ymin = -60), 
               crs = st_crs(4326)))
fishing_pts_sub <- st_intersection(fishing_pts, e)

  plot(fishing_pts_sub, pch=20, add=TRUE)
    plot(e, add=TRUE)
  • This is cool, thanks! The issue I have is that I need to combine this particular piece of work with outputs from the adehabitatHR package, which is based on sp. :-(
    – user303287
    May 25, 2022 at 16:08
  • 1
    @user303287 follow this approach and then convert sf objects to sp for adehabitatHR.
    – aldo_tapia
    May 25, 2022 at 16:18
  • 1
    It is very easy to go back-and-forth between sf and sp. For sf to sp x <- as(x, "Spatial") and sp to sf x <- as(x, "sf"). This can be done inside a call to a function requiring a different spatial class. Same goes for raster objects, just use raster::raster (on a terra object) or terra::rast (on any raster object) to go back and forth. May 25, 2022 at 16:20

To clip a dataframe with spatial info to a desired study area:

(1) Convert the dataframe to a spatialpointdataframe by assigning spatial info.

# where your dataframe has the following columns:
# Lat, Lon (spatial info), and variable 1 (e.g. fishing effort info)

spdf <- dataframe

coordinates(spdf) = ~ Lon+Lat
crs <-"+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"
proj4string(spdf) <- crs
class(spdf) # this should now be a spatialpointdataframe

(2) Create a raster object with spatial extent of interest

r = raster(ext=extent(-70, -55, -60, -38), res=c(0.1,0.1))
r[] <- 1 # randomly assign a value to the raster cells
projection(r) <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"
crs(r) <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"

(3) Crop spatialpointdataframe by raster using crop function. tada.

spdfc <- crop(spdf, r, inverse = F) 


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.