2012-04-07 20 views
5

G'day, sto lavorando con un set di dati di grandi dimensioni con ~ 125.000 posizioni lon/lat con data, per record di presenza/assenza di specie. Per ogni località, voglio capire come era il tempo in ogni luogo della data e durante i 3m prima della data. Per fare ciò, ho scaricato i dati meteorologici giornalieri per una determinata variabile meteorologica (ad esempio, temperatura massima) durante il periodo di 5 anni in cui sono stati presi i dati. Ho un totale di 1.826 file raster, tutti tra 2-3mb.Lavorare con molti dati e molti raster in R?

Avevo pianificato di raggruppare tutti i file raster, quindi estrarre un valore da ogni raster (1.826) per ogni punto. Ciò produrrebbe un file enorme che potrei usare per cercare le date che mi servono. Questo, tuttavia, non è possibile perché non posso impilare quel numero di raster. Ho provato a dividere i raster in stack di 500, questo funziona, ma i file che produce sono circa 1 Gb e molto lenti (righe, 125.000; colonne, 500). Inoltre, quando provo a portare tutti questi file in R per creare un frame di grandi dimensioni, non funziona.

Mi piacerebbe sapere se c'è un modo per lavorare con questa quantità di dati in R, o se c'è un pacchetto che potrei usare per aiutare. Potrei usare un pacchetto come ff? Qualcuno ha qualche suggerimento per un metodo meno energivoro per fare ciò che voglio fare? Ho pensato a qualcosa come una funzione lapply, ma non ho mai usato uno prima e non sono davvero sicuro da dove cominciare.

Qualsiasi aiuto sarebbe davvero eccezionale, grazie in anticipo per il vostro tempo. Il codice che sto attualmente usando senza successo è sotto.

Cordiali saluti, Adam

library(raster) 
library(rgdal) 
library (maptools) 
library(shapefiles) 

# To create weather data files, first set the working directory to the appropriate location (i.e., maxt) 
# list of raster weather files 
files<- list.files(getwd(), pattern='asc') 
length(files) 

memory.size(4000) 
memory.limit(4000) 

# read in lon/lat data 
X<-read.table(file.choose(), header=TRUE, sep=',') 
SP<- SpatialPoints(cbind(X$lon, X$lat)) 

#separate stacks into mannageable sizes 
s1<- stack(files[1:500]) 
i1 <- extract(s1,SP, cellnumbers = True, layer = 1, nl = 500) 
write.table(i1, file="maxt_vals_all_points_all_dates_1.csv", sep=",", row.names= FALSE, col.names= TRUE) 
rm(s1,i1) 
s2<- stack(files[501:1000]) 
i2 <- extract(s2,SP, cellnumbers = True, layer = 1, nl = 500) 
write.table(i2, file="maxt_vals_all_points_all_dates_2.csv", sep=",", row.names= FALSE, col.names= TRUE) 
rm(s2,i2) 
s3<- stack(files[1001:1500]) 
i3 <- extract(s3,SP, cellnumbers = True, layer = 1, nl = 500) 
write.table(i3, file="maxt_vals_all_points_all_dates_3.csv", sep=",", row.names= FALSE, col.names= TRUE) 
rm(s3,i3) 
s4<- stack(files[1501:1826]) 
i4 <- extract(s4,SP, cellnumbers = True, layer = 1, nl =325) 
write.table(i4, file="maxt_vals_all_points_all_dates_4.csv", sep=",", row.names= FALSE, col.names= TRUE) 
rm(s4,i4) 

# read files back in to bind into final file !!! NOT WORKING FILES ARE TOO BIG!! 
i1<-read.table(file.choose(),header=TRUE,sep=',') 
i2<-read.table(file.choose(),header=TRUE,sep=',') 
i3<-read.table(file.choose(),header=TRUE,sep=',') 
i4<-read.table(file.choose(),header=TRUE,sep=',') 

vals<-data.frame(X, i1, i2, i3 ,i4) 
write.table(vals, file="maxt_master_lookup.csv", sep=",", row.names= FALSE, col.names= TRUE) 
+0

Non riesco a ricordare la mole di dati che ho fatto a questo, ma ho avuto fortuna portando una tonnellata o raster in una lista nominata. Potresti aver capito che l'estrazione sarà probabilmente il tuo collo di bottiglia temporale, quindi proverei a limitare il più possibile l'uso. Ho sperimentato l'utilizzo della famiglia di funzioni tapply/by/ddply per dividere un grande dataframe in gruppi, quindi utilizzare l'estrazione su ciascun gruppo sul file appropriato (che, nel tuo caso, sarebbe una sorta di raggruppamento della data), quindi riassemblare , ma non ho avuto un sacco di successo con questo. – blindjesse

+0

Sarebbe abbastanza semplice leggere quei file in un array ff, quindi impostare l'estrazione per i punti da quelli. È possibile fornire un collegamento a uno o due file per lavorare o produrre dati utilizzabili con il codice? Inoltre, usi file.choose() per leggere i file, ma perché non i nomi che hai usato per scriverli? – mdsumner

+0

Ma, perché leggerli tutti in una volta lo stesso? Perché non basta estrarre un file raster alla volta? E, se il risultato finale è troppo grande per la pre-inizializzazione come un singolo oggetto, basta aggiungere un file mentre si va. – mdsumner

risposta

5

mi avrebbero fatto il file raster estratto uno alla volta, e aggiungere i risultati di file, come si va.

I cheat sto facendo un elenco di matrici, ma dal momento che il raster può prendere un nome file o una matrice (tra le altre cose) e puoi indicizzare con "[[" su un vettore di carattere dovrebbe funzionare più o meno lo stesso nel tuo caso .

files <- list(volcano, volcano * 2, volcano * 3) 
library(sp) 
SP <- SpatialPoints(structure(c(0.455921585146703, 0.237608166502031, 0.397704673508124, 0.678393354622703, 0.342820219769366, 0.554888036966903, 0.777351335399613, 0.654684656824567), .Dim = c(4L, 2L))) 

library(raster) 
for (i in seq_len(length(files))) { 

    r <- raster(files[[i]]) 
    e <- extract(r, SP) 
    ## print(e) ## print for debugging 
    write.table(data.frame(file = i, extract = e),"cellSummary.csv", col.names = i == 1, append = i > 1, sep = ",", row.names = FALSE) 
} 
+0

Ciao @mdsummer, grazie per questa risposta. Sono abbastanza sicuro che funzionerà perfettamente. Al momento sta creando un data.frame in sole due colonne, il che significa che dopo alcune estrazioni non ha più righe su cui scrivere. Sto cercando di capire come modificare il codice per ottenere i numeri di cella, quindi le informazioni estratte in ogni colonna procedurale. A me sembra che il tuo codice dovrebbe farlo, non sono sicuro di cosa sia sbagliato. Grazie ancora per il vostro aiuto, molto apprezzato. – Adam

+0

PS. questo è l'errore che ottengo. Errore in .rasterObjectFromFile (x, band = band, objecttype = "RasterLayer",: Impossibile creare un oggetto RasterLayer da questo file. – Adam

+0

Non possiamo aiutarti se non fornisci il file oi dettagli su di esso. i tuoi file non sono quelli che ti aspetti io immagino – mdsumner

0

Sto usando elaborazione parallela e una forma di coltura in base al numero di cellule. Questa funzione prenderà qualsiasi punto spaziale o poligono e restituirà i valori da un grande stack raster. Questa è una variante sul codice good example for large polygons.

Per i miei dati ci vogliono circa 350 secondi usando extract, o 32 secondi su un server Linux 16 core. Spero che aiuti qualcuno!

# Define Functions 
    extract_value_point_polygon = function(point_or_polygon, raster_stack, num_workers){ 
      # Returns list containing values from locations of spatial points or polygons 
      lapply(c('raster','foreach','doParallel'), require, character.only = T) 
      registerDoParallel(num_workers) 
      ply_result = foreach(j = 1:length(point_or_polygon),.inorder=T) %do%{ 
       print(paste('Working on feature: ',j,' out of ',length(point_or_polygon))) 
       get_class= class(point_or_polygon)[1] 
       if(get_class=='SpatialPolygons'|get_class=='SpatialPolygonsDataFrame'){ 
        cell = as.numeric(na.omit(cellFromPolygon(raster_stack, point_or_polygon[j], weights=F)[[1]]))} 
       if(get_class=='SpatialPointsDataFrame'|get_class=='SpatialPoints'){ 
        cell = as.numeric(na.omit(cellFromXY(raster_stack, point_or_polygon[j,])))} 
       if(length(cell)==0)return(NA) 
       r = rasterFromCells(raster_stack, cell,values=F) 
       result = foreach(i = 1:dim(raster_stack)[3],.packages='raster',.inorder=T) %dopar% { 
        crop(raster_stack[[i]],r) 
       } 
       result=as.data.frame(getValues(stack(result))) 
       return(result) 
      } 
      endCluster() 
      return(ply_result) 
    }