2017-09-22 114 views
1

我遇到内存问题,R给出Can not allocate vector of size XX Gb错误消息。我有一堆日常文件(12784天),以netcdf格式给出1305x378(经纬度)网格的海面温度。这样每天就可以得到493290分,在移除新地区(陆地点)时减少到约245000。处理R中的大数据集

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

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

另一个策略,我试过没有成功的一刻,它已经顺序读取所有的NC文件,然后提取每个点的所有日常值,并找到趋势。然后我只需要保存一个245000点的数据帧。但我认为这会很耗时,而不是适当的R方式。

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

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

  1. 提取单点时间序列来计算个人的发展趋势,并形成一个较小的数据帧
  2. 子集日常文件切片,以避免内存不足的问题,但有很多dataframes结束/文件
  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] 

} 

日期星是日期变量名

编辑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 
+5

怎么样如果你把所有的数据放在适当的数据库中并从那里查询? –

+0

这可能会运行,但我只有基本的数据库知识,我也有一个截止日期,如果可能,我更喜欢基于R的解决方案。谢谢。 – pacomet

+0

这可以通过大小(1305x378)x 12784(磁盘上47GB)的'big.matrix'(bigmemory)或'FBM'(bigstatsr)来完成。你应该填写一栏(每一天)。但是你感兴趣的是每一行,然后你可以转置它(例如'big_transpose'),然后在每列(每个点)上操作。 –

回答

1

所以,在Filebacked大矩阵(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 
} 
+0

看来它在第一个月里工作正常,创建一个493290行和31列的矩阵,所有点/行为一个月/列。要尝试全套,35年。 – pacomet

+0

Hi @F.Privé矩阵有一个问题,我认为后台文件位于我的系统的/ tmp中,但没有足够的可用空间。可以将它移动到有足够磁盘空间的/ home吗? – pacomet

+0

@pacomet Yeap,有一个参数。 –