# How to create a regular, square grid, and find centroid by factors using R

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`.
``````

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

EDIT:

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
sf_1.0-9

• The grid doesn't care about the size of your data. Its a 0.5x0.5 grid that spans your data. Commented 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. Commented 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". Commented 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. Commented Jan 30, 2023 at 15:05

Starting with your `coords` data frame, this seems to work:
``````aggregate(cbind(x,y) ~ scientificName, data=coords, FUN=mean)