Reputation: 81
I have a dataframe with Longitudes and Latitudes and I would like to create a 0.5x0.5 degrees grid that shows which lat, long fall within it. So far, I have tried several solutions, including some found here on stackoverflow, that use cut
and expand.grid
as well as code that uses the package "sp" but none has worked out for me (maybe I simply can't implement them).
Any suggestions on how I can group my data into a 0.5x0.5 degrees grids?
Latitude | Longitude |
---|---|
31.602 | -39.848 |
31.675 | -39.467 |
31.747 | -39.083 |
32.152 | -36.795 |
32.218 | -36.408 |
32.285 | -36.022 |
32.348 | -35.635 |
32.412 | -35.247 |
32.475 | -34.858 |
32.535 | -34.47 |
32.595 | -34.082 |
32.677 | -33.707 |
32.763 | -33.323 |
Thank you all for your time and effort.
Edit: My best effort was this snippet
library(tidyverse)
pos <- dassem %>%
dplyr::select(Latitude, Longitude)
gridx <- seq(from = min(dassem$Longitude), to = max(dassem$Longitude), by = 2)
gridy <- seq(from = min(dassem$Latitude), to = max(dassem$Latitude), by = 2)
xcell <- unlist(lapply(pos$Longitude,function(x) min(which(gridx>x))))
ycell <- unlist(lapply(pos$Latitude,function(y) min(which(gridy>y))))
pos$cell <- (length(gridx) - 1) * ycell + xcell
pos
# A tibble: 45,647 x 3
Latitude Longitude cell
<dbl> <dbl> <dbl>
1 51.7 -54.9 638
2 51.9 -54.5 638
3 52.1 -54.1 638
4 52.3 -53.7 639
5 52.5 -53.2 639
6 52.7 -52.8 639
7 52.9 -52.4 639
8 53.2 -52.0 639
which, as you can see, does not return a 2x2 degrees grid (I set it to 2x2, and not 0.5x0.5).
Upvotes: 0
Views: 736
Reputation: 5232
library(tidyverse)
library(sf)
df_sf <- df %>%
st_as_sf(coords = c("lon", "lat"), crs = 4326)
grid <- df_sf %>%
st_bbox() %>%
st_as_sfc() %>%
st_make_grid(cellsize = 0.5)
df %>%
mutate(polygon_id = st_intersects(df_sf, grid) %>% map_int(1))
Upvotes: 1
Reputation: 160397
It's not perfectly clear what your expected output is, but I'll give a few options:
dassem <- structure(list(Latitude = c(31.602, 31.675, 31.747, 32.152, 32.218, 32.285, 32.348, 32.412, 32.475, 32.535, 32.595, 32.677, 32.763), Longitude = c(-39.848, -39.467, -39.083, -36.795, -36.408, -36.022, -35.635, -35.247, -34.858, -34.47, -34.082, -33.707, -33.323)), class = "data.frame", row.names = c(NA, -13L))
I'll start with a 1-degree grid (arbitrary):
degx <- degy <- 1 # grid sizes
gridx <- seq(min(dassem$Longitude), max(dassem$Longitude) + degx, by = degx)
gridy <- seq(min(dassem$Latitude), max(dassem$Latitude) + degy, by = degy)
dassem %>%
mutate(
x = findInterval(Longitude, gridx),
y = findInterval(Latitude, gridy)
)
# Latitude Longitude x y
# 1 31.602 -39.848 1 1
# 2 31.675 -39.467 1 1
# 3 31.747 -39.083 1 1
# 4 32.152 -36.795 4 1
# 5 32.218 -36.408 4 1
# 6 32.285 -36.022 4 1
# 7 32.348 -35.635 5 1
# 8 32.412 -35.247 5 1
# 9 32.475 -34.858 5 1
# 10 32.535 -34.470 6 1
# 11 32.595 -34.082 6 1
# 12 32.677 -33.707 7 2
# 13 32.763 -33.323 7 2
This provides the grid indices for each point, if that's of any interest.
If you don't need the individual indices, you can combine them (as I did for that image):
dassem %>%
mutate(
cell = paste(findInterval(Longitude, gridx),
findInterval(Latitude, gridy),
sep = ",")
)
# Latitude Longitude cell
# 1 31.602 -39.848 1,1
# 2 31.675 -39.467 1,1
# 3 31.747 -39.083 1,1
# 4 32.152 -36.795 4,1
# 5 32.218 -36.408 4,1
# 6 32.285 -36.022 4,1
# 7 32.348 -35.635 5,1
# 8 32.412 -35.247 5,1
# 9 32.475 -34.858 5,1
# 10 32.535 -34.470 6,1
# 11 32.595 -34.082 6,1
# 12 32.677 -33.707 7,2
# 13 32.763 -33.323 7,2
Upvotes: 0