【问题标题】:Extract row data using a raster grid使用栅格网格提取行数据
【发布时间】:2020-07-19 03:35:46
【问题描述】:

我有一个分辨率为 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 度栅格网格单元位置,那就太好了。

任何帮助将不胜感激。

【问题讨论】:

标签: r coordinates gis shapefile r-raster


【解决方案1】:

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

示例数据

#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 中。如果您有许多物种,您想为 rasterize 参数分配一个文件名,例如 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 &lt;- sum(ss&gt;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

【讨论】:

  • 谢谢你的回复,我也试试这个,感觉挺复杂的,但是对于像我这样的相对新手来说,R就是这样!
  • 嗨,我设法制作了一个栅格堆栈,其中包含每个物种的范围(总共 963 个物种,每个物种 1 个栅格)我需要做的是将它与 0.5 度的栅格网格结合起来我创建的比例尺,我一直在尝试使用提取功能,但它似乎不起作用。我努力按照上面的代码进行操作,但它确实有帮助。你知道如何组合它们吗?
  • 请提出一个新问题来解决这个问题
【解决方案2】:

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

我强烈建议您使用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(.)))

那么我们来做一个简单的dataframe:

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 会比手动编码技术更快。

【讨论】:

  • 您好,感谢您的快速回复,我尝试了上述方法,但出现错误:CPL_geos_binop(st_geometry(x), st_geometry(y), op, par, pattern, : std ::bad_alloc 我不确定这意味着什么 - 另外,我如何从每个网格单元的列表中拉出网格的中心点(纬度和经度)?我想要做的是获取每个网格的物种编号每个 0.5 网格单元中存在的物种。我已经用其他数据源完成了它,但是这个源是一个空间多边形,因此所有问题,因为我以前没有处理过......
  • 我指的是物种编号,而不是物种编号
  • 我看起来是内存问题see here。在您的示例数据框中,您有许多重复的行。在您的真实数据框中是这种情况吗?因为在这种情况下,您可以首先通过计算不同的 (lon, lat, id) 来聚合 df,然后进行合并。减少df 的大小将有助于减少内存需求。
  • 也许spatial indexes 可以帮忙
  • 谢谢,我会按照你说的缩小尺寸。祝你有美好的一天!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多