![](/img/trans.png)
[英]Subset R rasterstack based on difference in raster layers grid cell numbers
[英]How to manipulate large `RasterStack` object and write all raster grid in plain-text data in R?
在R中处理非常大的RasterStack
对象时,我遇到了一些挑战。这是主要的故事,我已经从欧洲气候评估网站下载了网格数据 ( 下载网格数据的站点以及我感兴趣的网格数据的链接) )。 因此,我的第一步是将R中的数据作为RasterStack
对象导入。 然后,我打算只裁剪特定国家/地区的栅格网格,所以我使用raster::crop
做到了。 我的最终目标是计算每个网格单元的年平均温度。 这是我从原始原始RasterStack
对象中裁剪的网格覆盖范围,其中网格分辨率定义为0.25-degree
分辨率:
这是我拍摄的R脚本:
library(raster)
library(ncdf4)
library(R.utils)
library(maptools)
raw_netCDF = raster::stack("~/tg_0.25deg_reg_1995-2010_v17.0.nc") # read downloaded gridded data in R
data(wrld_simpl)
Germany <- wrld_simpl[wrld_simpl@data$NAME == "Germany",]
deu_ext <- extent(Germany)
Germany_ <- crop(raw_netCDF, deu_ext)
但是在解决方案Germany_
提出了一个挑战。 第一个挑战是处理大型RasterStack
对象中的缺失值。 如果我不处理大型RasterStack
对象中的缺失值,那么在新生成的裁剪栅格网格中,所有缺失值都将变为零,这会导致读取温度观测值(例如摄氏零度)时产生混乱。 因此,我以两种不同的方式处理大型RasterStack
对象中的缺失值。 第一个在下面:
raw_netCDF_ = raster::reclassify(raw_netCDF , cbind(NA, -999))
但是raster::reclassify
总是由于内存问题而失败。 所以这不是一个好的解决方案。 我尝试使用raster::calc
来处理非常大的RasterStack
对象中的缺失值,但是即使我在功能强大的计算机上运行相同的操作,它也非常慢。 因此,使用raster::calc
处理缺失值确实不是一个好主意。 这是下面的R脚本
raw_netCDF_ = raster::calc(raw_netCDF , function(x) { ifelse(is.na(x), -999, x) })
我想进行简单的统计,以计算整个网格覆盖范围内每个网格单元的年平均温度,并以干净和简单的明文数据生成其输出。 在最终栅格中,纯文本格式的栅格数据仅包含栅格坐标及其年平均温度。 对RasterStack
对象执行这样的操作对我来说不是一个普通的任务。
也许,必须有一个可能的最佳解决方案,以正确处理非常大的RasterStack
对象,并确保原始原始数据中的所有缺失值都可以正确保存在德国的裁剪栅格中。
所需输出 :
在导出的纯文本数据中,我希望整个德国网格的年平均Temp
为16年,如下所示:
> ann_mean_temp_1996_1999
long lat net_1996_precip net_1997_temp net_1997_temp net_1998_temp net_1999_temp net_2000_temp
1: 6.125 47.375 84.4 86.4 83.4 81.4 80.4 87.4
2: 6.375 47.375 89.3 88.3 84.3 81.3 846.3 846.3
3: 6.625 47.375 80.0 85.0 80.0 83.0 88.0 87.0
4: 6.875 47.375 84.4 83.4 85.4 86.4 82.4 80.4
5: 7.125 47.375 83.0 85.0 84.0 89.0 83.0 84.0
---
1112: 13.875 54.875 63.8 68.8 66.8 67.8 65.8 66.8
1113: 14.125 54.875 69.6 65.6 61.6 60.6 62.6 63.6
1114: 14.375 54.875 60.5 61.5 62.5 67.5 69.5 64.5
1115: 14.625 54.875 62.9 67.9 68.9 67.9 64.9 68.9
1116: 14.875 54.875 64.6 67.6 66.6 62.8 64.6 63.5
如果可以在R中操纵非常大的RasterStack
对象,如何获得具有正确分辨率的预期栅格数据(丢失值将得到适当处理),并对每个栅格的所有日常温度观测应用简单的统计信息? 我怎样才能做到这一点? 是否可以操作RasterStack
对象并将所有栅格网格数据写入R中的纯文本数据( ASCII
或csv
)中? 任何有效的方法来完成此任务? 还有其他想法吗? 谢谢
我会反对您的观点,即这是一个“很大”的RasterStack
,但除此之外,我认为您想要做的应该很简单。
因此,首先我将数据加载和裁剪到德国范围内:
library(raster)
library(ncdf4)
library(R.utils)
library(maptools)
r <- stack('tg_0.25deg_reg_1995-2010_v17.0.nc')
data(wrld_simpl)
Germany <- wrld_simpl[wrld_simpl@data$NAME == "Germany",]
r_crop <- crop(r,Germany)
#Let's take a look:
plot(r_crop[[1]])
plot(Germany,add=T)
边界形状不是特别漂亮,但是可以完成工作。 此外,您还可以看到在北部,仍正确指示了NoData的值,如下所示:
r_crop[[1]][1,1]
# NA
在接下来的步骤中,我仅使用层名称提取年份,然后使用lapply
计算每年的均值:
nms <- names(r_crop)
yrs <- unique(sub('X(\\d+).+','\\1',nms))
yrs[1]
# [1] "1995"
annual_means <- lapply(yrs,function(x) mean(r_crop[[grep(x,nms)]],na.rm=TRUE))
这将为您提供一个名为annual_means
的列表, annual_means
包含每年的栅格数据,代表该年的年均值。 现在,您可以将它们堆叠在一起(使用do.call(stack,annual_means)
),分别进行处理,或者您可能想要做的就是将它们以csv的形式写入磁盘:
# first take a look
plot(annual_means[[1]])
# write to disk
write.table(as.matrix(annual_means[[1]]),'ANNUAL_MEAN_TEMP_1995.csv',quote = F,row.names = F,col.names = F,sep = ';')
编辑 :
annual_means
是一个列表,其中每个元素都有一个栅格,表示从原始数据集的每日观测值计算出的平均温度。 因此,列表中的元素将与年份一样多。
上面的write.table
示例仅显示了这些年份之一,这意味着如果这是您想要的输出,则需要为列表中的所有元素复制该步骤。
write.table
步骤所做的只是将栅格转换为矩阵,然后将其写入磁盘。 结果将是一个矩阵,其行数和列数与栅格本身一样多,每个像元之间用分号分隔(我个人喜好)。
编辑2:
只是为了说明我的意见:
您有16年的数据,如yrs
向量所示:
yrs
#[1] "1995" "1996" "1997" "1998" "1999" "2000" "2001" "2002" "2003" "2004"
#[11] "2005" "2006" "2007" "2008" "2009" "2010"
现在, annual_means
是一个长度为16的列表,每年有一个单层栅格,这是根据每日数据为整个德国计算的全年平均值。
这是一个示例输出:
annual_means[[1]]
# class : RasterLayer
# dimensions : 31, 37, 1147 (nrow, ncol, ncell)
# resolution : 0.25, 0.25 (x, y)
# extent : 5.75, 15, 47.25, 55 (xmin, xmax, ymin, ymax)
# coord. ref. : +proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0
# data source : in memory
# names : layer
# values : 3.329288, 11.32734 (min, max)
如您所见,栅格的分辨率为0.25度(这是数据的原始分辨率),这将导致栅格包含31行和37列,覆盖德国。
要获得所需的输出:
我将首先用相应年份命名列表条目,以使其更加可见(您可以跳过此步骤):
names(annual_means) <- yrs
现在,我将提取每个栅格的坐标,并使用值创建一个数据lapply
(使用lapply
遍历列表):
result <- lapply(annual_means, function(x) data.frame(long = coordinates(x)[,1],lat = coordinates(x)[,2],temp_mean =x[]))
现在,我们可以检查数据框的顶部,例如2000年:
head(result$`2000`)
# long lat temp_mean
# 1 5.875 54.875 NaN
# 2 6.125 54.875 NaN
# 3 6.375 54.875 NaN
# 4 6.625 54.875 NaN
# 5 6.875 54.875 NaN
# 6 7.125 54.875 NaN
如您所见,第一个像素都是NoData(就像在图中所示),这就是您想要的。
所以最后, result
是一个列表,每个元素都是特定年份的数据帧,其中包含long
, lat
和temp_mean
列。
为了100%复制您想要的输出,现在可以再次在result
列表上循环以将temp_mean
列名称更改为特定于一年的名称(这是完全可选的):
for (i in seq_along(result)){
colnames(result[[i]])[3] <- paste0('Net_',names(result)[i],'_Temp')
}
给你:
head(result$`2000`)
# long lat Net_2000_Temp
# 1 5.875 54.875 NaN
# 2 6.125 54.875 NaN
# 3 6.375 54.875 NaN
# 4 6.625 54.875 NaN
# 5 6.875 54.875 NaN
# 6 7.125 54.875 NaN
编辑3:
要以所有方式获得一个数据帧,可以执行以下操作:
ann_mean_temp_1996_1999 <- cbind(result[[1]][,1:2],do.call(cbind,lapply(result,function(x) x[,3])))
colnames(ann_mean_temp_1996_1999)[3:ncol(ann_mean_temp_1996_1999)]<- unlist(lapply(result,function(x) colnames(x)[3]))
第一个lapply
将long / lat(这并不会一直改变)与每个列表项的第三列(即T-MEAN)绑定在一起。
第二个lapply
提取并为温度再次分配列名称,这似乎在过程中丢失了。 比使用lapply
可能有一个更优雅的解决方案,但是它确实可以做到。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.