使用栅格网格提取行数据

时间:2020-04-07 01:57:59

标签: r coordinates gis shapefile r-raster

我有一个分辨率为0.5度(r)的栅格网格和一个具有3列的数据框(my_df):long,lat和id。数据框代表物种发生记录。

我要做的是确定栅格网格的每个0.5度像元中存在哪些种类,并且对于每个像元,仅保留每个种类的1条记录(my_df的行数超过90,000,000行),因此如果一个0.5度像元如果只有一个物种,则在栅格网格像元的一排长条上有经纬度,然后是数据框中的物种ID。其他栅格网格像元可能包含数百种,因此可能有数百行。

最终,我想创建一个数据框,其中每个物种所在的0.5度栅格网格的纬度和纬度以及那里存在的物种ID(每个物种一行)。

我已经按照...创建了一个栅格网格。

ext <- extent(-180.0, 180, -90.0, 90.0)
gridsize <- 0.5
r <- raster(ext, res=gridsize)
crs(r) <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"

和一个数据框,最初是SpatialPolygonsDataframe ...

A tibble: 6 x 3
   long   lat id   
  <dbl> <dbl> <chr>
1  16.5 -28.6 0    
2  16.5 -28.6 0    
3  16.5 -28.6 0    
4  16.5 -28.6 0    
5  16.5 -28.6 0    
6  16.5 -28.6 0 
etc
etc

...但是不确定如何进行其余方法。我曾尝试对数据进行栅格化,提取点等,但是我不断遇到错误,并且不确定要使用哪种正确的方法来实现目标。

或者,如果有人知道如何直接从SpatialPolygonsDataFrame中提取物种名称,则该空间在0.5度栅格网格像元位置上包含每个物种的范围多边形,那就太好了。

任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:1)

如果我猜对了,您想匹配单元格内的点。我认为您正在寻找基于点和多边形之间的交点的空间连接。

我强烈建议您使用sf包而不是sp对象。那就是我要向你建议的。

首先,使用st_make_grid函数创建网格

library(sf)
library(dplyr)

ext <- raster::extent(-180.0, 180, -90.0, 90.0)

grid <- st_bbox(ext) %>% 
  st_make_grid(cellsize = 0.5, what = "polygons") %>%
  st_set_crs(4326)
grid <- grid %>% st_sf() %>% mutate(id_cell = seq_len(nrow(.)))

然后让我们看一个简单的数据框:

df <- data.frame(long = 16.51, lat = -28.6, id = 0)
df <- df %>% sf::st_as_sf(coords = c("long","lat"), crs = 4326)

df

Simple feature collection with 1 feature and 1 field
geometry type:  POINT
dimension:      XY
bbox:           xmin: 16.51 ymin: -28.6 xmax: 16.51 ymax: -28.6
epsg (SRID):    4326
proj4string:    +proj=longlat +datum=WGS84 +no_defs
  id            geometry
1  0 POINT (16.51 -28.6)

然后,您需要使用st_join函数。默认情况下,空间连接基于交集:

df %>% sf::st_join(grid, left = TRUE)

although coordinates are longitude/latitude, st_intersects assumes that they are planar
Simple feature collection with 1 feature and 2 fields
geometry type:  POINT
dimension:      XY
bbox:           xmin: 16.51 ymin: -28.6 xmax: 16.51 ymax: -28.6
epsg (SRID):    4326
proj4string:    +proj=longlat +datum=WGS84 +no_defs
  id id_cell            geometry
1  0   88234 POINT (16.51 -28.6)

我假设您想要左加入(报告您的所有观点)。您可以更改该选项。我认为使用sf比手工编码技术要快。

答案 1 :(得分:0)

使用点数据,您可以像这样

示例数据

#species
set.seed(0)
n <- 20
spp <- data.frame(lon=runif(n, -180, 180), lat=runif(n,-90,90), sp=sample(5, n, replace=TRUE)) 

# raster
library(raster)
# for the example I use a resolution of 90, rather than 0.5 
r <- raster(res=90)

现在计算每个位置的单元号并列表。我这样做的方式是返回计数,而不只是返回存在/不存在

spp$cell <- cellFromXY(r, spp[, c("lon", "lat")])
tb <- table(spp$cell, spp$sp)

获取每个单元格的lon / lat

xy <- xyFromCell(r, as.integer(rownames(tb)))
result <- cbind(xy, tb)
colnames(result)[1:2] <- c("lon", "lat")
result
#   lon lat 1 2 3 4 5
#1 -135  45 0 0 1 0 0
#2  -45  45 0 2 1 0 0
#3   45  45 1 0 0 2 0
#4  135  45 0 1 0 0 1
#5 -135 -45 1 2 0 0 0
#6  -45 -45 0 1 0 1 0
#7   45 -45 1 1 0 0 0
#8  135 -45 1 0 1 2 0

对于多边形数据(以及点数据),您可以使用raster::rasterize

示例多边形数据

library(raster)
p1 <- rbind(c(-180,-20), c(-140,55), c(10, 0), c(-140,-60), c(-180,-20))
hole <- rbind(c(-150,-20), c(-100,-10), c(-110,20), c(-150,-20))
p1 <- list(p1, hole)
p2 <- rbind(c(-10,0), c(140,60), c(160,0), c(140,-55), c(-10,0))
p3 <- rbind(c(-125,0), c(0,60), c(40,5), c(15,-45), c(-125,0))
spp <- data.frame(species=letters[1:3], stringsAsFactors=FALSE)
pols <- spPolygons(p1, p2, p3, attr=spp)

栅格化每个物种并合并到RasterStack中。如果您有很多种类,则要为栅格化参数分配文件名,例如filename = paste0("sp_", i, ".tif")

usp <- unique(spp$species)
r <- raster(res=0.5)
s <- list()
for (i in 1:length(usp)) {
    p <- pols[pols$species == usp[i], ]
    s[[i]] <- rasterize(p, r, field=1, fun="count")
}       
ss <- stack(s)

(对于物种丰富度,请sr <- sum(ss>0, na.rm=TRUE)

创建所需的输出

m <- as.matrix(ss)
m[is.na(m)] <- 0
# to remove rows with no species 
i <- which(rowSums(m) > 0)
xy <- xyFromCell(r, i)  
output <- cbind(xy, m[i,])
colnames(output) <- c("lon", "lat", usp)
head(output)
#        lon   lat a b c
#[1,]  -0.25 59.75 0 0 1
#[2,] 139.75 59.75 0 1 0
#[3,]  -1.25 59.25 0 0 1
#[4,]  -0.75 59.25 0 0 1
#[5,]  -0.25 59.25 0 0 1
#[6,]   0.25 59.25 0 0 1