从堆积的栅格对象计算选定区域

时间:2017-02-23 20:26:34

标签: r raster r-raster map-projections

因为我最近才开始使用R进行空间分析,而我是 无论是地理学家还是空间数据专家,我都有 - 什么 我认为这是一个相对简单的问题。我想算一算 符合某些要求的堆积栅格对象的一部分区域 条件。 更具体地说,来自深海的数据集 南大西洋,我已经堆叠了两个光栅对象(深度和斜率) 在坐标系(WGS84)和x-y(Lat-Long)中进一步相同 位置。从堆叠的栅格对象,我想 提取位于(比如)1000到4000米深度的部分,用a 坡度超过10度。我想知道什么是区域 范围是平方公里,我想将它添加到以前 绘制地图。以下是一个可重复的例子:

# Raster object containing depth values
dpt <-  raster(ncol=623, nrow=815, xmx=-31.72083, xmn=-38.50417,
ymn=-33.8875, ymx=-28.70417)
values(dpt) <- sample(-200:-5000, size=(nrow(dpt)*ncol(dpt)), replace=T)

# Raster object containing slope values
slp <- raster(ncol=623, nrow=815, xmx=-31.72083, xmn=-38.50417,
ymn=-33.8875, ymx=-28.70417)
values(slp) <- sample(0:30, size=(nrow(slp)*ncol(slp)), replace=T)

# Stack raster objects
stk <- stack(dpt,slp)


 # Colour palette
 colrs <- colorRampPalette(c("navyblue","dodgerblue3","cyan2","green2","darkgoldenrod1"))
 # Plot raster map; does not look like ocean floor because of "sample"
 plot(dpt, xlab="Longitude", ylab="Latitude", col=colrs(100), font.lab=2,
 cex.lab=1.5, las=1)


 # Create a blank copy of previous raster plot
 selectAtt <- raster(dpt)
 # Fill in cells where Attribute(s) meet(s) conditions
 selectAtt[stk$layer.1 <= -1000 & stk$layer.1 >= -4000 & stk$layer.2 >=
 10] <- 90
 # Set object projection
 projection(selectAtt) <- CRS("+proj=longlat +ellps=WGS84")
 # Plot selection in previous raster
 plot(selectAtt, col="red", add=TRUE, legend=F, proj4string=crswgs84)

然后,我的问题是:满足给定条件的深度(第1层)和斜率(第2层)的面积(在总面积内)是多少?在这种情况下,仰角在-1000和-4000米之间,并且倾斜角度> 10度。

我最初的想法是:

> area(selectAtt)

给出答案:

class       : RasterLayer 
dimensions  : 623, 815, 507745  (nrow, ncol, ncell)
resolution  : 0.008323108, 0.008319957  (x, y)
extent      : -38.50417, -31.72083, -33.8875, -28.70417  (xmin, xmax, ymin, ymax)
coord. ref. : +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +towgs84=0,0,0 
data source : in memory
names       : layer 
values      : 0.7083593, 0.7481782  (min, max)

关于Raster对象的基本信息......它给了我奇怪的感觉,我没有得到我提出的问题的答案。也许我没有问正确的问题?无论如何,它没有告诉我任何符合我条件的地区的大小。

然后我做了:

a <- stk[stk$layer.1 <= -1000 & stk$layer.1 >= -4000 & stk$layer.2 >= 10]
 area(a, na.rm=T)

 # This gives me the error message:
 Error in (function (classes, fdef, mtable)  :
         unable to find an inherited method for function ‘area’ for signature ‘"matrix"’

我试图找到这实际意味着什么,并且它似乎是S3和S4功能之间的不匹配,即使我不确切知道它们是什么。

无论如何,我认为我对空间数据提出了一个相对简单的查询,即基于来自光栅堆栈中几个层的信息的选择对应的区域是什么?我在这里错过了什么?任何帮助是极大的赞赏 !

3 个答案:

答案 0 :(得分:1)

有多种方法可以访问图层和栅格堆栈的值。我更喜欢以下内容:

#select first layer of raster stack 
stk[[1]]

#get values of second layer
stk[[2]][]

现在回到你的问题:

当我想计算符合特定条件的像素区域时,我会执行以下操作(使用小栅格时):

numberOfPixels <- sum(stk[[1]][] <= -1000 & stk[[1]][] >= -4000 & stk[[2]][] >= 10, na.rm=T)

这将为您提供符合定义条件的像素数。如果你在一个投影坐标系中工作(你在WGS 84工作,因此你无法从中计算准确的区域),你只需将numberOfPixels乘以光栅的分辨率:

area <- numberOfPixels * (res(stk)[1] * res(stk)[2])

如果要获得平方米的面积,请将栅格重新投影到投影坐标系。例如进入UTM。在你的情况下,这个可能是一个很好的选择(请注意你的范围跨越多个区域):http://www.spatialreference.org/ref/epsg/wgs-84-utm-zone-24s/

stk <- projectRaster(from=stk, crs="+proj=utm +zone=24 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs")

然后再次:

numberOfPixels <- sum(stk[[1]][] <= -1000 & stk[[1]][] >= -4000 & stk[[2]][] >= 10, na.rm=T)
area <- numberOfPixels * (res(stk)[1] * res(stk)[2])
area
[1] 258898897920 

答案 1 :(得分:0)

好的,这是一种可能的不同方法,基于将栅格单元格转换为多边形,然后计算利用包geosphere的多边形区域:

require(geosphere)
polys = rasterToPolygons(stk)
polys_sub = subset(polys, (layer.1 <= -1000 & layer.1 >= -4000 & layer.2 >= 10))
> sum(areaPolygon(polys_sub))/1E6  #in km2

[1] 157035.2

这与OP从cellStats方法获得的结果非常相似(约2%的折扣),并且与reprojection方法完全不同。根据我在areaPolygon的帮助下的理解,这应该是一种数字上正确的方法。尽管如此,我仍然不了解@maRtin answer的不同结果。

顺便说一句,对于OP:你为什么要设置一个如此的例子&#34;奇怪的&#34;参考系统(纬度/经度,不同的x / y分辨率)?

答案 2 :(得分:0)

首先进行一些健全检查......

我们在这里处理的实际区域是什么? 我们将基于您的堆栈,我们将使用res()来提取分辨率。手动抓住它们很容易,但我更愿意打电话给它们。

 length(stk)*res(stk)[1]*res(stk)[2]

 70.32058

所以我得到~70.3作为堆栈的实际区域。我只是从你提供的数据中得到这个,所以如果CRS或者预测很难,那就是你。如果我们的工作是找到我们子集的区域并发现它与此截然不同,我们误入歧途。

现在我将从您执行此操作的第4块代码开始:

 a <- stk[stk$layer.1 <= -1000 & stk$layer.1 >= -4000 & stk$layer.2 >= 10]

所以现在我们有了一个图层,我们在其中对stk进行了子集,使得它现在是符合条件的值列表。我们不需要该列表,我们真的只想知道它包含多少元素。

替换为:

 a<-length(stk[stk$layer.1 <= -1000 & stk$layer.1 >= -4000 & stk$layer.2 >= 10])

因为我们只想知道列表中有多少元素......

现在,使用res()来获取x和y分辨率:

 a*res(stk)[1]*res(stk)[2]

结果:

 29.80777

根据我们之前计算的光栅面积,这似乎是合理的,约占总面积的42%。这对我来说似乎很合理。

关于其他答案评论中的投影和坐标系的问题,这是一个问题。但是你可以确保你的预测不会让你想要做的事情变得有意义。还要记住,简单地重新分配投影系统与重新投影不同。可能是我在R中使用栅格工作时最常见的错误之一就是重新分配CRS而不是重新投射栅格。它可以帮助您了解您的数据的形式以及您需要做什么来完成您想要做的数学运算。