在 R 中处理大规模气候数据集的解决方案

Solutions for handling large-scale climate dataset in R

提问人:Shunrei 提问时间:11/16/2023 最后编辑:Shunrei 更新时间:11/16/2023 访问量:57

问:

我正在分析从 1950 年到 2023 年的 ERA5 气候数据,涵盖 73 年。 该数据集的每日时间分辨率和空间分辨率为 0.25° (1440 x 720)。

每个年度数据都存储在一个 NetCDF 文件中,其中包含大约 365 个图层。

尝试将这些组合到单个堆栈中会导致大约 27000 个层,这对我的计算机来说是压倒性的,甚至工作场所集群也难以处理这个数量。

由于我是处理大规模数据集的新手,因此我正在寻求有关管理和处理此类数据的最佳实践和有效解决方案的建议。

注意:我更喜欢使用数据帧而不是 NetCDF 文件,因为我将执行时间序列分析。

注2:未来将进行不同类型的分析。它非常广泛:从简单的统计,到指数计算等。在网格单元级别。

注 3:我听说过以较小的块处理数据。在 R 中有一个好的包可以做到这一点吗?

R 栅格 NetCDF 区块

评论

0赞 Patrick 11/16/2023
您提到了空间分辨率,但空间范围是多少?换句话说,每个文件有多少行和多少列?
0赞 Patrick 11/16/2023
您需要对数据进行什么样的分析?由于您有每小时数据,我认为它是每日总和/最大值/最小值等。您正在处理哪些变量?您是否需要组合不同的变量来产生结果?请在您的帖子中添加几行,描述您要进行的分析。
0赞 Patrick 11/16/2023
每日数据 - >月度统计数据,但其他评论与上述相同
0赞 Shunrei 11/16/2023
嗨,帕特里克,正如帖子中所述,是气候变量。对于分析来说,它很大。从简单到更复杂的。我们仍处于探索阶段。是的,在某些时候,我需要将它们组合在一起(在应用统计模型时)。
1赞 Matteo De Felice 11/18/2023
不幸的是,我仍然没有找到在 R 中执行此操作的方法。 目前,当我分析文件 >10 GB 时,我总是在 Python 中使用 xarray + dask......

答:

0赞 Patrick 11/16/2023 #1

73 年来,ERA5 数据已覆盖全球,可为您提供每个变量(如温度或降水量)的数据点。没有分块,任何计算机系统都不会处理它。1440 * 720 * 73 * 365.2425 = 27.6 billion

首先,忘记在整个数据集上使用 s。首先,您需要将其处理到合理的大小,然后才能使用进一步分析(如果您确实需要它)。data.framedata.frame

其次,ERA5 数据使用 or 日历。这意味着您可以使用标准类,例如,创建用于处理数据的因子。但是,由于 ERA5 数据符合 CF 元数据约定,因此最好使用 CFtime 包,这样可以更好地控制时间序列。gregorianstandardDate

按位置分样

分解数据集的一个明显选项是按位置逐个像素地对时间序列进行采样。然而,这是一个糟糕的选择,因为您的数据分布在 73 个文件中,并且每个文件内的存储组织使得这是一个非常慢的选项(数据分散在每个文件中)。I/O 噩梦,甚至不考虑它。

时间切片

最好的办法是单独处理每个文件,然后在整个时间序列中将年度输出组合到数据对象中。如果从每日数据转到月度统计数据,则每个统计数据将有大约 9 亿个数据点(例如,每月最大 T、每月最小 T)。仍然非常重要,但在一台好的计算机上是可行的。这看起来有点像这样:

# Attach necessary packages
library(ncdf4)
library(CFtime)
library(abind)

# Get a list of your 73 ERA5 files
lf <- list.files("~/your/path/to/ERA5", "\\.nc$", full.names = TRUE)

# Open the files sequentially and process
mon <- lapply(lf, function(fn) {
  # Open the file and create a CFtime object
  nc <- nc_open(fn)
  cf <- CFtime(nc$dim$time$units, nc$dim$time$calendar, nc$dim$time$vals)

  # Create a factor to make monthly statistics
  fac <- CFfactor(cf, "month")

  # Read and process the data, here the monthly maximum T
  data <- ncvar_get(nc, "t2m")
  aperm(apply(data, 1:2, tapply, fac, max), c(2, 3, 1))
  dimnames(data) <- list(as.vector(nc$dim$longitude$vals),
                         as.vector(nc$dim$latitude$vals),
                         levels(fac))
  nc_close(nc)
  data
}

# `mon` is a list with 73 elements, each with 12 layers of monthly max T
# Now put them all into 1 object
all_mon <- abind(mon, along = 3)

这仍然为您提供了一个非常大的对象,但至少它是可管理的。如果你想要不同的统计信息,你可以编写自己的函数,然后调用它。aperm(apply(data, 1:2, tapply, fac, <<<here>>>), c(2, 3, 1))

评论

0赞 Shunrei 11/16/2023
非常感谢帕特里克,唯一的问题是我们将处理每日/每周数据。不是每月一次。因此,如果我理解您的代码,无论我想在我的文件上应用什么功能,我都必须以这种方式处理每个年度文件?
1赞 Patrick 11/16/2023
Yes, this is the basic approach to processing data in smaller chunks. If you stay at the daily resolution then your data set will never reduce so every parameter you derive will have a total size of 50GB - 100GB. You are then probably better off storing the derived parameters per year, to keep the files manageable. Weeks have additional complications of definition (start on Monday or Sunday? which is week 1 in the year?) and they straddle year boundaries so I'd stay clear if you can.
0赞 Shunrei 11/16/2023
What about creating data cubes with defined dividing grid coordinates ?
0赞 Patrick 11/17/2023
Yes, you could easily implement your own data cubes by dividing up the lon-lat plane into, say, 10 x 10 degree tiles of all data per year. That would then become a mix of temporal slicing and sampling by location: I/O will be less optimal but on the CPU things may be better due to less RAM load.
0赞 Shunrei 11/17/2023
Do you recommend a way to be able to do it on nc files and transform them into raster stack cubes ?