我正在尝试裁剪一些raster data并进行一些计算(getting the mean sea surface temperature,具体而言)。
但是,在比较裁剪之前,在进行计算之前,栅格数据的范围与在裁剪结果数据之前进行计算的结果相同。
栅格数据的原始范围是-180, 180, -90, 90 (xmin, xmax, ymin, ymax)
,我需要将其裁剪到由纬度和经度坐标定义的任何所需区域。
这是我正在测试的脚本:
library(raster) # Crop raster data
library(stringr)
# hadsstR functions ----------------------------------------
load_hadsst <- function(file = "./HadISST_sst.nc") {
b <- brick(file)
NAvalue(b) <- -32768 # Land
return(b)
}
# Transform basin coordinates into numbers
morph_coords <- function(coords){
coords[1] = ifelse(str_extract(coords[1], "[A-Z]") == "W", - as.numeric(str_extract(coords[1], "[^A-Z]+")),
as.numeric(str_extract(coords[1], "[^A-Z]+")) )
coords[2] = ifelse(str_extract(coords[2], "[A-Z]") == "W", - as.numeric(str_extract(coords[2], "[^A-Z]+")),
as.numeric(str_extract(coords[2], "[^A-Z]+")) )
coords[3] = ifelse(str_extract(coords[3], "[A-Z]") == "S", - as.numeric(str_extract(coords[3], "[^A-Z]+")),
as.numeric(str_extract(coords[3], "[^A-Z]+")) )
coords[4] = ifelse(str_extract(coords[4], "[A-Z]") == "S", - as.numeric(str_extract(coords[2], "[^A-Z]+")),
as.numeric(str_extract(coords[4], "[^A-Z]+")) )
return(coords)
}
# Comparison test ------------------------------------------
hadsst.raster <- load_hadsst(file = "~/Hadley/HadISST_sst.nc")
x <- hadsst.raster
nms <- names(x)
months <- c("01","02","03","04","05","06","07","08","09","10","11","12")
coords <- c("85E", "90E", "5N", "10N")
coords <- morph_coords(coords)
years = 1970:1974
range = 5:12
# Crop before calculating mean
x <- crop(x, extent(as.numeric(coords[1]), as.numeric(coords[2]),
as.numeric(coords[3]), as.numeric(coords[4])))
xMeans <- vector(length = length(years)-1,mode='list')
for (ix in seq_along(years[1:length(years)])){
xMeans[[ix]] <- mean(x[[c(sapply(range,function(x) grep(paste0(years[ix],'.',months[x]),nms)))]], na.rm = T)
}
mean.brick1 <- do.call(brick,xMeans)
# Calculate mean before cropping
x <- hadsst.raster
xMeans <- vector(length = length(years)-1,mode='list')
for (ix in seq_along(years[1:length(years)])){
xMeans[[ix]] <- mean(x[[c(sapply(range,function(x) grep(paste0(years[ix],'.',months[x]),nms)))]], na.rm = T)
}
mean.brick2 <- do.call(brick,xMeans)
mean.brick2 <- crop(mean.brick2, extent(as.numeric(coords[1]), as.numeric(coords[2]),
as.numeric(coords[3]), as.numeric(coords[4])))
# Compare the two rasters
mean.brick1 - mean.brick2
这是mean.brick1 - mean.brick2
:
class : RasterBrick
dimensions : 5, 5, 25, 5 (nrow, ncol, ncell, nlayers)
resolution : 1, 1 (x, y)
extent : 85, 90, 5, 10 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=longlat +datum=WGS84
data source : in memory
names : layer.1, layer.2, layer.3, layer.4, layer.5
min values : 0, 0, 0, 0, 0
max values : 0, 0, 0, 0, 0
正如你所看到的,两个RasterBricks完全相同,对于任意选择的坐标都不可能,如下面用一个小矩阵所示:
我做错了什么?在使用它们进行计算之前裁剪数据应该明确地给出不同的结果。
答案 0 :(得分:3)
好的,我将在上一个问题中继续post:
我们从完整的hadsst.raster
砖开始(对于具有可重复的示例,可以在我之前的答案中使用我的解决方案的第一部分进行伪造)。
因此,此数据集的维度为180, 360, 516
,表示180行,360列和516个时间层。
从技术上讲,光栅是一个矩阵,这可能是它的样子:
只是一堆矩阵层(准确地说是516),其中每个像素都是精确对齐的。这里我只有三个示例图层,其余部分由三个点表示。
因此,如果我们进行时间平均,我们基本上提取单个像素的所有值并采用它们的均值(或任何其他平均操作)。这由红色方块表示。
这也说明了为什么裁剪不影响时间平均的原因:
如果我们说橙色方块是我们感兴趣的程度,并且我们在>平均之前执行裁剪操作,我们基本上会丢弃此方块周围的所有值。之后,我们再次获取所有图层上每个像素的所有值并执行平均值。
现在应该清楚了,为什么当你丢弃橙色方块周围的像素时它并不重要。您还可以计算它们的平均值,然后丢弃这些值,只留下橙色方块的值。如果你已经确定你不需要它们进行进一步的计算,它就没有任何意义。 无论如何,广场内的价值不会受到影响。
当我们谈论空间平均时,它通常意味着对单个图层中的像素求平均值,在这种情况下可能超过橙色矩形内的值。
两个常见的操作是
焦点平均将对每个像素采用定义数量的相邻像素的所有值的平均值(最常见的是3x3
平方,其中要定义的像素是中心像素。 / p>
聚合实际上是采用多个像素并将它们组合成更大的像素。这意味着不仅会对此像素的值进行平均,而且还会使得到的栅格具有较少的单个像素和较粗糙的分辨率。
好的,为您找到实际的解决方案:
我假设您有一个由范围aoi
定义的感兴趣区域:
aoi <- extent(xmin,xmax,ymin,ymax)
你要做的第一件事是裁剪初始砖块以减少计算负担:
hadsst.raster_crp <- crop(hadsst.raster,aoi)
下一步是时间平均,我们使用我在其他post的解决方案中定义的函数:
hadsst.raster_crp_avg <- hadSSTmean(hadsst.raster_crp, 1969:2011, first.range = 11:12, second.range = 1:4)
好的,现在您的时间平均值仅适用于您感兴趣的区域。下一步取决于您的最终目标。 据我所知,您只需要为您感兴趣的区域提供每个时间平均值的单一平均值。
如果是这种情况,可能是离开实际栅格域并继续使用基础R的正确时间:
res <- lapply(1:nlayers(hadsst.raster_crp_avg),function(ix) mean(as.matrix(hadsst.raster_crp_avg[[ix]])))
这将为您提供一个列表,其中包含与您的hadsst.raster_crp_avg
砖一样多的元素。
使用lapply
,我们遍历图层,将每个图层转换为矩阵,然后计算所有元素的平均值,为整个感兴趣的区域留下每个平均时间步长的单个值。
更进一步,您可以使用unlist
将其转换为向量,并将其添加到data.frame
或执行您喜欢的任何其他操作。
希望这很清楚,这就是你要找的东西。
最佳