I want to create a regular, square grid of .5x.5 degree around my sampling points and find latlong centroid by factors.

I have a data frame which have three columns: (1) the "scientificName" column containing some species names; and its respective (2) longitude and (3) latitude values.

> head(coords)
            scientificName         x          y
1  Aceratobasis_cornicauda -40.56560 -19.901400
2  Aceratobasis_macilenta  -49.00881 -25.516721
3  Aceratobasis_nathaliae  -53.99830 -26.505600
4  Amazoneura_ephippigera  -73.18583  -4.372778
5  Amazoneura_ephippigera  -64.68917  -3.512500
6  Amazoneura_juruaensis   -72.90000  -7.618056

I started by creating a SpatialPoints object, and transforming it using sf pck.

coordinates(coords) <- ~long + lat
prj<-'+proj=longlat +datum=WGS84'
coords <- SpatialPoints(coords, proj4string = CRS(prj))
data_sf <- st_as_sf(coords,
                    coords = c("long", "lat"),
                    crs = st_crs("+proj=longlat +datum=WGS84"))

Then I created my grid using sf::st_make_grid:

grid <- data_sf %>%
  st_bbox() %>%
  st_as_sfc() %>%
  st_make_grid(cellsize = c(0.5, 0.5), 
               crs = "+proj=longlat +datum=WGS84",
               square = T) |> st_as_sf()

Here I was expecting my grid to have the same length as my df. Though sf consists in a large sfc_POLYGON of 153.900 elements. To workaround it I subset my data:

grid_subset <- grid[st_intersects(data_sf, grid) |> unlist(), ]

As expected, now my subset have the same length as my df. But now I'm kinda stuck, and assuming my coordinates fell in the cells' centroid (I'm not exactly sure about that; @Spacedman shed some light on this issue, see comments). Finally, to find the centroid of my coordinates by "scientificName" factors I tried:

centroids <- grid_subset %>%
  group_by(scientificName) %>%
  summarise(centroid = st_centroid(st_union(grid[grid])))

But no success. I keep getting the error:

Error in `st_as_sf()`:
! Must group by variables found in `.data`.
✖ Column `scientificName` is not found.

Converting grid_subset to df and adding scientificName to it also didn't work. I just get a new error:

Error in `summarise()`:
! Problem while computing `centroid = st_centroid(st_union(grid[grid]))`.
ℹ The error occurred in group 1: scientificName = "Aceratobasis_cornicauda".

In sum, (1) I want a grid around my sampling points and (2) find latlong centroid by factors (or (2) before (1)).


I tried a different approach. First by estimating my factors' centroid, then creating the grid:

data <- read.table("clipboard", header=T)
centroids <- data %>%
  group_by(scientificName) %>%
  summarize(centroid_x = mean(x),
            centroid_y = mean(y))
sp_centroids <- SpatialPoints(centroids[, c("centroid_x", "centroid_y")], 
                              proj4string = CRS("+proj=longlat +datum=WGS84"))

scientific_names <- centroids$scientificName
attr(sp_centroids, "scientificName") <- scientific_names

centroids_sf <- st_as_sf(centroids,
                    coords = c("centroid_x", "centroid_y"),
                    crs = "+proj=longlat +datum=WGS84")

grid_sf <- centroids_sf %>%
  st_bbox() %>%
  st_as_sfc() %>%
  st_make_grid(cellsize = c(0.5, 0.5), 
               crs = "+proj=longlat +datum=WGS84",
               square = T) 

centroids_sf <- st_transform(centroids_sf, st_crs(grid_sf))|> st_as_sf()

centroids_sf consists in a list of the same length as my factors. However, I'm not being able to properly convert my centroids_sf to a spatial object that I can use in raster().

Here is part of my session info:

other attached packages: [1] raster_3.5-21 dplyr_1.0.10 sp_1.5-0

  • 1
    The grid doesn't care about the size of your data. Its a 0.5x0.5 grid that spans your data.
    – Spacedman
    Jan 30, 2023 at 14:20
  • "assuming my coordinates fell in the cells' centroid" - a centroid is a point, so a coordinate can't fall in a centroid... I'm just struggling to understand what you are trying to do here.
    – Spacedman
    Jan 30, 2023 at 14:28
  • I thought I could create a grid around my points. My mistake. Anyway, I need to find the centroid of my points, and group them by "sicentificName". Jan 30, 2023 at 14:50
  • You can create a grid around your points, its what st_make_grid does. Finding the centroid of a set of points, assuming equal weight per point, is the same as computing the mean X and Y coordinate independently. You could do that from the data frame with X and Y coords, or (I think) use some sf functions to merge the points to MULTIPOINT features and then use st_centroid.
    – Spacedman
    Jan 30, 2023 at 15:05

1 Answer 1


Starting with your coords data frame, this seems to work:

aggregate(cbind(x,y) ~ scientificName, data=coords, FUN=mean)
  • I managed to calculate the mean of my latlong and find its centroids through: centroids <- coords %>% group_by(scientificName) %>% summarize(centroid_x = mean(x), centroid_y = mean(y)) Though now I'm having some problems to intersect it with the grid I created. Soon I will update the issue. Jan 30, 2023 at 18:03
  • Sounds like you should make a new question for this rather than editing this one.
    – Spacedman
    Jan 30, 2023 at 20:46
  • This question is connected to: Intersecting objects and converting it to simple features so I can use 'raster', R gis.stackexchange.com/questions/450921/… Jan 31, 2023 at 17:46

Your Answer

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

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