2016-01-21 76 views
0

並行處理I具有大的柵格(> 20 GB),並希望每個轉換成CSV文件的特殊格式如下:轉換rasterstack到csv中的R

unique_key_column 
x_coordinate 
y_coordinate 
layer1_values 
layer2_values 

library(raster) 
r <- raster(nrows=10,ncols=10) 
r[] <- rnorm(10) 
stack <- stack(r,r,r,r,r) 

    #create function to convert coordinate to special format 
    # -34.9 will be 1034900000 
    # sxxxdddddd, where s= sign (-=1, +=2), x=degrees (34=034), 
    # and d = decimal (.9=900000) 

formatCoordinate <- function(x){ 
    first_part <- ifelse(x < 0 , "1","2") 
    second_part <- abs(as.integer(x)) 
    #make sure 3 part has 6 decimal places, then convert it to string 
    third_part <- substr(gsub(".+\\.","",as.character(format(round(x, 2), 
          nsmall = 6))),1,6) 
    result <- sprintf("%s%03d%s",first_part,second_part,third_part) 
    result 
} 

    #the actual processing 

stack =readAll(stack) 
names(stack) <-c("l1", "l2", "l3", "l4", "l5") 
#convert rasterStack to dataframe 
stackPoints <- as.data.frame(rasterToPoints(stack)) 
#format x and x coordinates 
colX <- formatCoordinate(stackPoints$x) 
colY <- formatCoordinate(stackPoints$y) 
#combine formatted x and y coordinates to compose a unique key 
pK <- paste0(colX, colY) 
stackPoints["key"] <- pK 
col_idx <- grep("key", names(stackPoints)) 
stackPoints <- stackPoints[, c(col_idx, (1:ncol(stackPoints))[-col_idx])] 
#write results to a csv file 
write.table(stackPoints, "r.csv", row.names=F, sep=";", dec=",", append=F) 

上面的代碼適用於小型光柵,但對於大型光盤,我無法將堆疊加載到RAM中。 有沒有辦法將我的代碼轉換爲使用並行處理?即讀取光柵並使用多核寫入csv,而不需要將光柵加載到RAM(Mac OSX 10.11和Ubuntu 14.04,每個8核)。 最好的,

+0

什麼是您的操作系統?您需要使用的並行庫取決於操作系統 – C8H10N4O2

+0

感謝您的提示。我有Mac El-Captain和Ubuntu(在兩臺不同的計算機上)。我在問題中添加了這個細節:D – user22364

+0

請參閱[這裏](https://cran.r-project.org/web/packages/doParallel/vignettes/gettingstartedParallel.pdf)開始。 – C8H10N4O2

回答

1

首先你想弄清楚如何在單線程上編寫一個循環,因爲從for()foreach()將是非常簡單的。我對RasterStack對象不熟悉,但看起來它具有可與nlayers(x)一起計數的圖層,可用x[[i]]提取。

所以首先我將編寫和調試是這樣的:

for(i in 1:nlayers(stack)){ 
    #convert layer of rasterStack to dataframe 
    layer_pts <- as.data.frame(rasterToPoints(stack[[i]])) 

    #write layer_pts to a csv file 
} 

然後foreach()容易。請記住,您需要使用raster軟件包啓動每個線程。爲了更快地合併,我推薦data.table

library(foreach) 
library(doMC) 
library(data.table) 
registerDoMC(detectCores() - 2) # for me this is 40 - 2 = 38 
layer_list <- 
    foreach(i = 1:nlayers(stack), .packages = c('raster', 'data.table')) %dopar% { 
    #convert layer of rasterStack to data.table 
    layer_pts <- as.data.table(rasterToPoints(stack[[i]])) 
    setkey(layer_pts, x, y) # data.table can key on x and y, no synthetic key needed 
    layer_pts 
    } 

tbl_out <- Reduce(merge, layer_list) # uses keys from setkey 

# if you wanted the "key" column (but not essential) 
tbl_out[, key:= paste0(formatCoordinate(x), formatCoordinate(y)) ] 

write.csv(tbl_out, 'r.csv') 

請注意,如果內存不足,則可能必須減少使用的內核數量。例如,基於試驗和錯誤的registerDoMC(4)

+0

這太棒了!現在我知道如何輕鬆使用foreach:D我在數據上嘗試了它,它運行得很好,速度也很快。但是我面臨一個問題,一個CSV是爲一個圖層生成的(總數約爲450 CSV)。由於NA值的不同,CSVs的行數不同,因此我無法輕鬆地將它們以每個堆棧一個CSV的方式連接在一起(即使使用唯一密鑰。是否有解決方法?更改循環以剪切小塊,然後將其轉換爲CSV (然後將它們加在一起)可以產生一致的列數,但是它會花費更長的時間並且需要更多的RAM,所以 – user22364

+0

@ user22364確定你的第一句話讓我覺得你想每個光柵有一個CSV,但是現在我明白你在找什麼對於''layer1_values,layer2_values'等所有在同一行的CSV。我會考慮它。 – C8H10N4O2

+0

我非常感謝你的幫助:D – user22364