2012-04-07 10 views
5

G'day, pracuję z dużym zbiorem danych z ~ 125 000 lokalizacjami z datą, dla zapisów obecności/nieobecności gatunków. W każdym miejscu chcę sprawdzić, jaka była pogoda w każdym miejscu na dzień iw czasie 3 minut przed datą. W tym celu pobrałem codzienne dane pogodowe dla danej zmiennej pogodowej (np. Maks. Temperatury) w okresie 5 lat, w którym dane zostały pobrane. Mam łącznie 1826 plików rastrowych, wszystkie pomiędzy 2-3mb.Praca z dużą ilością danych i dużą ilością rastrów w R?

Planowałem ułożyć wszystkie pliki rastrowe, a następnie wyodrębnić wartość z każdego rastra (1 826) dla każdego punktu. W ten sposób powstanie ogromny plik, którego mogę użyć do wyszukania potrzebnych dat. Nie jest to jednak możliwe, ponieważ nie mogę układać w stos wielu rastrów. Próbowałem podzielić rastry na stosy 500, to działa, ale pliki, które produkuje, mają około 1 Gb i są bardzo powolne (wiersze, 125 000, kolumny, 500). Ponadto, gdy próbuję przenieść wszystkie te pliki do R, aby utworzyć dużą ramkę danych, to nie działa.

Chciałbym wiedzieć, czy istnieje sposób pracy z tą ilością danych w R, lub jeśli istnieje pakiet, który mógłbym użyć, aby pomóc. Czy mogę użyć pakietu takiego jak ff? Czy ktoś ma jakieś sugestie dotyczące mniej energochłonnej metody wykonywania tego, co chcę robić? Myślałem o czymś w rodzaju funkcji lapply, ale nigdy wcześniej jej nie użyłem i nie jestem pewien, od czego zacząć.

Każda pomoc będzie naprawdę świetna, z góry dzięki za poświęcony czas. Kod, którego obecnie używam bez powodzenia, znajduje się poniżej.

poważaniem, 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

Nie mogę sobie przypomnieć ogromu danych, które zrobiłem, ale miałem szczęście przynosząc tonę lub rastry do nazwanej listy. Być może odkryłeś, że ekstrakt będzie prawdopodobnie twoim wąskim gardłem, więc starałbym się ograniczyć jego użycie w jak największym stopniu. Eksperymentowałem z użyciem rodziny funkcji tapply/by/ddply, aby podzielić dużą ramkę danych na grupy, a następnie użyłem ekstraktu w każdej grupie na odpowiednim pliku (który w twoim przypadku byłby pewnego rodzaju grupowaniem dat), a następnie ponownie składałem , ale nie miałem z tym wielkiego sukcesu. – blindjesse

+0

Byłoby dość proste, aby odczytać te pliki do tablicy FF, a następnie ustawić ekstrakcję dla punktów z nich. Czy możesz podać link do jednego lub dwóch plików do pracy lub tworzenia użytecznych danych za pomocą kodu? Używasz również pliku file.choose() do odczytywania plików, ale dlaczego nie nazwy używane do ich zapisu? – mdsumner

+0

Ale dlaczego i tak czytać je wszystkie naraz? Dlaczego po prostu nie wypakować jednego pliku rastrowego naraz? A jeśli ostateczny wynik jest zbyt duży, aby wstępnie zainicjować jako pojedynczy obiekt, po prostu dołącz go do pliku. – mdsumner

Odpowiedz

5

zrobiłbym ekstrakt jeden plik rastrowy na raz, i dołączyć wyniki do pliku, jak przejść.

Oszukuję, tworząc listę macierzy, ale ponieważ raster może przyjmować nazwę pliku lub matrycę (między innymi) i można indeksować za pomocą "[[" na wektorze znaków, powinno działać prawie tak samo w twoim przypadku .

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

Witam @mdsummer, dziękuję za tę odpowiedź. Jestem prawie pewien, że to będzie działać idealnie. W tej chwili tworzy on dane.frame w tylko dwóch kolumnach, co oznacza, że ​​po kilku ekstrakcjach zabraknie w nim wierszy do napisania. Próbuję dowiedzieć się, jak zmienić kod, aby uzyskać numery komórek, a następnie wyodrębnione informacje w każdej kolumnie postępowania. Dla mnie kod wygląda tak, jak powinien, nie jestem pewien, co jest nie tak. Jeszcze raz dziękuję za pomoc, bardzo doceniane. – Adam

+0

PS. to jest błąd, który dostaję. Błąd w pliku .rasterObjectFromFile (x, band = band, objecttype = "RasterLayer",: Nie można utworzyć obiektu RasterLayer z tego pliku – Adam

+0

Nie możemy pomóc, jeśli nie podasz pliku lub szczegółów na jego temat. Twoje pliki nie są tym, czego oczekujesz Wyobrażam sobie: – mdsumner

0

Używam przetwarzania równoległego i formy przycinania w oparciu o numer komórki. Ta funkcja pobiera dowolne punkty przestrzenne lub wielokąty i zwraca wartości z dużego stosu rastrów. Jest to wariant kodu good example for large polygons.

Dla moich danych zajmuje to około 350 sekund przy użyciu wyciągu lub 32 sekund na 16-rdzeniowym serwerze Linux. Mam nadzieję, że to komuś pomaga!

# 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) 
    }