1

我在 R 给出Can not allocate vector of size XX Gb错误消息时遇到了内存问题。我有一堆 netcdf 格式的每日文件(12784 天),在 1305x378(经纬度)网格中给出海面温度。这每天给出 493290 点,当移除 NA(超过陆地点)时减少到大约 245000。

我的最终目标是为每日文件中的 245000 个点中的任何一个构建一个时间序列,并找到每个点的时间趋势。我的想法是构建一个大数据框,每行一个点,每列一天(2450000x12784),这样我就可以将趋势计算应用于任何点。但是随后,在构建这样的数据框时,正如预期的那样,出现了内存问题。

首先,我尝试了一个我以前用来读取数据并通过读取 nc 文件然后融合数据来提取三列(lon-lat-sst)数据帧的脚本。当尝试一小部分天时,这会导致计算时间过长,并导致内存问题。然后我尝试将日常文件分成纵向切片;这避免了内存问题,但 csv 输出文件太大并且该过程非常耗时。

我尝试过的另一种策略没有成功,它是顺序读取所有 nc 文件,然后提取每个点的所有每日值并找到趋势。然后我只需要保存一个 245000 点数据框。但我认为这将是耗时的,而不是正确的 R 方式。

我一直在阅读big.memoryff尝试声明 big.matrix 或 3D 数组(1305 x 378 x 12784)的包,但现在还没有成功。

面对这个问题的适当策略是什么?

  1. 提取单点时间序列以计算单个趋势并填充较小的数据框
  2. 对切​​片中的每日文件进行子集以避免内存问题,但以大量数据帧/文件结尾
  3. 尝试用 bigmemory 或 ff 包解决内存问题

在此先感谢您的帮助

编辑 1 添加代码以填充矩阵

library(stringr)
library(ncdf4)
library(reshape2)
library(dplyr)

# paths
ruta_datos<-"/home/meteo/PROJECTES/VERSUS/CMEMS/DATA/SST/"
ruta_treball<-"/home/meteo/PROJECTES/VERSUS/CMEMS/TREBALL/"
setwd(ruta_treball)

sst_data_full <- function(inputfile) {

  sstFile <- nc_open(inputfile)
  sst_read <- list()

  sst_read$lon <- ncvar_get(sstFile, "lon")
  sst_read$lats <- ncvar_get(sstFile, "lat")
  sst_read$sst <- ncvar_get(sstFile, "analysed_sst")

  nc_close(sstFile)

  sst_read
}

melt_sst <- function(L) {
  dimnames(L$sst) <- list(lon = L$lon, lat = L$lats)
  sst_read <- melt(L$sst, value.name = "sst")
}

# One month list file: This ends with a df of 245855 rows x 33 columns
files <- list.files(path = ruta_datos, pattern = "SST-CMEMS-198201")

sst.out=data.frame()

for (i in 1:length(files) ) { 
  sst<-sst_data_full(paste0(ruta_datos,files[i],sep=""))
  msst <- melt_sst(sst)
  msst<-subset(msst, !is.na(msst$sst))

  if ( i == 1 ) {
  sst.out<-msst
  } else {
  sst.out<-cbind(sst.out,msst$sst)
  }

}

编辑 2 在先前(较小)数据帧中用于计算时间趋势的代码。原始数据是一个时间序列矩阵,每一列都是一个序列。

library(forecast)

data<-read.csv(....)

for (i in 2:length(data)){

var<-paste("V",i,sep="")
ff<-data$fecha
valor<-data[,i]  
datos2<-as.data.frame(cbind(data$fecha,valor))
datos.ts<-ts(datos2$valor, frequency = 365)

datos.stl <- stl(datos.ts,s.window = 365)

datos.tslm<-tslm(datos.ts ~ trend)

summary(datos.tslm)

output[i-1]<-datos.tslm$coefficients[2]

}

fecha 是日期变量名

编辑 2 来自 F. Privé 答案的工作代码

library(bigmemory)

tmp <- sst_data_full(paste0(ruta_datos,files[1],sep=""))

library(bigstatsr)
mat <- FBM(length(tmp$sst), length(files),backingfile = "/home/meteo/PROJECTES/VERSUS/CMEMS/TREBALL" )

for (i in seq_along(files)) {
  mat[, i] <- sst_data_full(paste0(ruta_datos,files[i],sep=""))$sst
}

使用此代码创建了一个大矩阵

dim(mat)
[1] 493290  12783
mat[1,1]
[1] 293.05
mat[1,1:10]
[1] 293.05 293.06 292.98 292.96 292.96 293.00 292.97 292.99 292.89 292.97
ncol(mat)
[1] 12783
nrow(mat)
[1] 493290
4

1 回答 1

1

因此,对于您在 Filebacked Big Matrix (FBM) 中读取的数据,您可以这样做

files <- list.files(path = "SST-CMEMS", pattern = "SST-CMEMS-198201*",
                    full.names = TRUE)

tmp <- sst_data_full(files[1])

library(bigstatsr)
mat <- FBM(length(tmp$sst), length(files))

for (i in seq_along(files)) {
  mat[, i] <- sst_data_full(files[i])$sst
}
于 2017-09-29T07:15:05.110 回答