Error in R: "one node produced an error: Argumento NA/NaN" when extracting raster values in package parallel version 4.2.2

I'm working on an R script to build a correlation matrix based on values extracted from WorldClim bioclimatic layers at specific geographic coordinates (WGS84).

I have a dataset (db) with 842 obs. of 45 variables for just one specie, where each row have metadata and important spatial data in the following columns:

  1. Load the dataset

  2. Load WorldClim raster layers (biosTotal)

  3. Extract raster values at the point locations

  4. Compute a correlation matrix

  5. Run the process in parallel to improve performance The code I’m using for extraction and correlation calculation is below:

    
    #1.- Carga de paquetes y definiciones previas:####
    rm(list=ls())
    list.of.packages <- c("tictoc","tidyverse","data.table","sp","raster","rgdal","parallel","devtools","snow", "doParallel")
    new.packages <- list.of.packages[!(list.of.packages %in% installed.packages()[,"Package"])]
    if(length(new.packages)) install.packages(new.packages);lapply(list.of.packages, library, character.only=T)
    
    
    if(!require(kuenm)){devtools::install_github("marlonecobos/kuenm")}
    library(kuenm)
    
    tic.clearlog()
    tic("1.- Carga de paquetes y definiciones previas", log=T)
    
    #ruta de la carpeta general, donde se encuentra toda la información y donde aparecerá la carpeta de resultados.
    wd<- "C:/modelosREPTILES"
    #Esta carpeta debe contener, antes de correr el script, los siguientes elementos: 
    ##01_Bios_presente: carpeta con las 19 bios presentes
    ##02_Bios_futuro: carpeta con subcarpetas para cada escenario-laboratorio con las bios futuro en su carpeta correspondiente
    ##03_todasM_shp: carpeta con el shapefile de la M (coordenadas geográficas WGS84 -GCS_WGS84-)
    ##bbdd.csv: archivo csv con la base de datos en formato DwC (el nombre puede cambiarse, siempre que se especifique en la variable csv)
    ##maxent.jar: programa MaxENT (archivo jar) 
    results<- "04_Resultados_pruebaScript"#Nombre de la carpeta que se va a crear con los resultados
    csv<-"Cor_hortulana0rep.csv"#Nombre del archivo con la bbdd en formato DwC
    test<-0.3 # % de test
    kept_JK<-FALSE #TRUE guardar modelos candidatos de modelado para JackKnife
    kept_MF<- FALSE #TRUE guardar modelos candidatos de modelado final, FALSE los borra 
    # y guarda solo el/los finales
    tiempos<- "tiempos_pruebaScript"#nombre archivo tiempos
    
    setwd(wd) #directorio de trabajo
    db<-fread(paste0(getwd(),"/", csv), sep=",", encoding="UTF-8") #lectura bd
    db$family= rep("C", dim(db)[1])
    db#Se extrae vector con sp a modelar segun criterio:
    #Si queremos modelar todas las especies le asignamos nulo spMod<-NULL
    ##En este caso se filtan las de mas de 4 observaciones
    
    
    ## CORRE SIEMPRE DESDE AQUI CUANDO CAMBIES LA SP 
    spMod<-db %>% group_by(scientificName) %>% count() %>% filter(n>5)%>%
      dplyr::select(scientificName) %>% pull()
    
    ##se eligen al azar 5 especies para probar
    #spMod<-spMod[sample(1:length(spMod),5)] #Desbloquear esta línea para las corridas de 5 especies aleatorias, como prueba
    
    spMod<-spMod [1:1]  ## ESTA REALIZADO HASTA LA SP 4,esta en 5
    ### cambias los numeros que estan aun lado de los puntos por ejemplo si queires la 3 pones 3:3
    write.csv(spMod, "spModeladas_pruebaScript.csv")
    toc(log=T)
    
    #2.- Carga funciones: ####
    tic("2.- Carga de funciones", log=T) 
    
    numCores <- detectCores() #detecta los nucleos de CPU
    carpetas<- function (db, results){   # Crea carpetas por especie
      dir.create(results)
      for(i in unique(db$scientificName)){
        y<-paste0(substring(i,1,3),"_",
                  substring(i,(str_locate(i," ")[1,1]+1))) #Acronimo de la especie
        dir.create(paste0(results,"/",y))
      }
    }
    presencias<-function (db, test, results){ #Crea por especie los Training/test puntos de acuerdo a la conf. previa
      for (i in unique(db$scientificName)){
        y<-paste0(substring(i,1,3),"_",
                  substring(i,(str_locate(i," ")[1,1]+1))) #Acronimo
        db_cols<- db %>% dplyr::select(scientificName, 
                                       decimalLatitude, decimalLongitude) %>% droplevels()
        x<- db_cols %>% dplyr::filter(scientificName==i)  %>%
          rename(LATITUDE=decimalLatitude,
                 LONGITUDE=decimalLongitude) %>%
          mutate (Clavesp=y)%>%
          dplyr::select(Clavesp, LONGITUDE, LATITUDE) # seleccion columnas para MaxENT
        write.csv(x,paste0(results,"/",y,"/Sp_joint.csv"), row.names = F) # Archivo joint
        train<-1-test
        Sp_test<-x[sample(1:nrow(x), nrow(x)*test), ]
        Sp_train<-x[sample(1:nrow(x), nrow(x)*train), ]
        write.csv(Sp_test, paste0(results,"/",y,"/Sp_test.csv"), row.names = F)
        write.csv(Sp_train, paste0(results,"/",y,"/Sp_train.csv"), row.names = F)
      }
    } #funcion que permite a partir de df en DwC, %test y carpeta donde colocar resultados,
    #genera una carpeta por especie y en cada una de ellas un csv con todos los registros, train y test con el formato para MaxENT
    
    
    #Seleccionar las BIOS a partir de la matriz de correlacion
    F_SVal<-function(i,matrizCorr,JK){
      vec=matrizCorr[i,]
      p=which(abs(vec)>0.85) #Porcentaje aceptado de umbral en el valor de correlación
      vm=data.frame(valores=JK[p],pos=p)
      vm$pos[which(vm$valores==max(vm$valores))]
    }
    colocarMaxEnt<- function (from= "maxent.jar", to=results){ #Copia Maxent en cada una de las carpetas de las especies
      for (i in sp){
        file.copy(from= "maxent.jar", to= paste0(results, "/", i))
      }  
    } #Coloca maxEnt
    organizarM<-function (allM=input, sp=sp){  #Busca la M con el nombre la especie codificada como 3letrasGénero_especie "Ade_adiastola.shp", la copia y la pega en la carpeta de la especie
      for (i in sp){
        l<-list.files(input,
                      pattern=i, full.names = T, recursive=T)
        dir.create(paste0(results, "/",i, "/M_shapefile"))
        file.copy(from= l, 
                  to=paste0(results, "/",i, "/M_shapefile"))
        file.rename(from=list.files(paste0(results, "/",i, "/M_shapefile"),full.names = T),
                    to=str_replace(list.files(paste0(results, "/",i, "/M_shapefile"),full.names = T), pattern="([.])", "_M."))
    
      }} #organiza M en cada carpeta de sp
    
    #MatCorrPAR2 Función para la matriz de correlación
    MatCorrPAR2<- function (sp=sp, biosTotal=biosTotal , results=results) {
      list.of.packages<-c("sp","raster","rgdal")#Paquetes requeridos para script
      lapply(list.of.packages, library,character.only=T)
      file<- read.csv(paste0(results, "/", sp ,"/Sp_joint.csv"))
      shp<-SpatialPointsDataFrame(coords=file[,c(2,3)], 
                                  data=file,
                                  proj4string=crs(biosTotal))
      writeOGR(obj = shp,layer = sp,
               dsn =paste0(results,"/",sp, "/Ptos_shapefile"),driver = "ESRI Shapefile", overwrite_layer = T)
      M<- readOGR(paste0(results,"/",sp,"/","M_shapefile"), layer=paste0(sp,"_M"))
    
      crop<-raster::crop(x=biosTotal, y=M)
      biosM<-raster::mask(crop, M)
    
      dir.create(paste0(results, "/", sp, "/M_var/TodasBios"), recursive=T)
      lapply(names(biosM), function(x){
        writeRaster (biosM[[x]], paste0(results, "/",sp, "/M_var/TodasBios/", x,".asc"))})
      pointsExtract<-data.frame(raster::extract(biosM, shp))
      Corr<-cor(na.omit(pointsExtract), use="complete.obs")
      dir.create(paste0(results, "/", sp, "/SelecVars"), recursive=T)
      write.csv(Corr, paste0(results,"/",sp,"/SelecVars/", "Corr_bios.csv"), row.names = F)
      pdf(paste0(results,"/",sp,"/","M_shapefile","/","plot",sp,".pdf"))
      plot(M, main=sp, lwd=3)
      plot(shp, col="red",lwd=2, add=T)
      dev.off()
    }
    preparacionG<-function(allBiosFuturo="02_Bios_futuro",results=results, G_varSet="G_var/BiosSelec", sp=sp){
      for (i in sp){
        listBiosSelec<-list.files(paste0(results,"/",i,"/M_var/BiosModelo/BiosSelec"),
                                  pattern="*.asc$")
        for (j in list.files(allBiosFuturo)){
          dir.create(paste0(results,"/",i,"/",G_varSet,"/",j), recursive=T)
          file.copy(from=paste0(allBiosFuturo,"/", j,"/", listBiosSelec), 
                    to=paste0(results,"/",i,"/",G_varSet,"/",j))
        }
      }
    }
    
    #Revisar la funcion preparacionG para paralelo con foreach y %dopar%
    #https://nceas.github.io/oss-lessons/parallel-computing-in-r/parallel-computing-in-r.html
    
    
    toc(log=T)
    
    
    #3.- Comprobaciones previas para modelamiento: ####
    tic("3.- Comprobaciones previas para modelamiento", log=T)
    #3.1 existe bd con campos correctos
    if(nrow(db) == 0  | is.null(nrow(db))) print("No se encuentra tabla de datos")
    if(nrow(db) != 0  | !is.null(nrow(db))){
      if(sum(!(c("scientificName", "decimalLatitude", "decimalLongitude") %in% names(db)))!=0){
        print("Revisar campos de nombre cientifico y coordenadas")
      }
    }
    #3.2 existe carpeta bios presentes
    dirs.wd<-list.files(getwd())
    if(!("01_Bios_presente" %in% dirs.wd))print("Falta carpeta bios presente")
    #3.3 existe carpeta bios futuro
    dirs.wd<-list.files(getwd())
    if(!("02_Bios_futuro" %in% dirs.wd))print("Falta carpeta bios futuro")
    #3.4 existen M para las sp a modelar?
    if (is.null(spMod)){especiesModelar<- unique(db$scientificName)}else {especiesModelar<-spMod}
    
    especiesModelar_nomResum<-paste0(str_sub(especiesModelar, 1,3),"_",
                                     str_sub(especiesModelar, str_locate(especiesModelar, " ")[,1]+1))
    v<-NULL
    for (i in especiesModelar_nomResum){
      v1<-length(list.files("03_todasM_shp", pattern=i))<3
      if(v1){print(paste0("La especie ", i, " no tiene una M correcta"))}
      v<-c(v,v1)
      if(sum(v)==0)cat("Todas las sp a modelar tienen M correcta")
    }
    toc(log=T)
    
    #4.- Preparacion carpetas sp y archivos de presencias a partir de bbdd ####
    tic("4.-Preparacion carpetas sp y archivos de presencias a partir de bbdd", log=T)
    
    #Genero una columna (Si/No) con las sp a modelar
    if(!is.null(spMod)){db<- db %>% mutate(Modelar=ifelse(scientificName %in% spMod,"Si", "No"))
    }else{db<- db %>% mutate(Modelar="Si")}
    
    db_filtro<- db %>%  filter(Modelar=="Si") %>%
      droplevels()#Filtro sp validadas no modeladas
    carpetas(db_filtro, results)
    presencias(db_filtro, test, results)
    
    #Se coloca cada M en su carpeta correspondiente
    sp<-list.dirs(results, full.names = F, recursive = F)
    input<- "03_todasM_shp"
    organizarM(input, sp)
    
    #Colocacion maxENt en cada sp
    colocarMaxEnt(from= "maxent.jar", to=results)
    toc(log=T)
    
    #5.- Matriz correlacion: carga de bios como stack. cortar M, extraccion valores bios y mat correlacion####
    
    tic("5.- Matriz correlacion", log=T)
    pathBios<- list.files(paste0("01_Bios_presente","/"),
                          pattern= "*.asc$", full.names=T, recursive=T)[c(-8,-9,-18,-19)] #Recomendacion de quitar estas variables
    biosTotal<- raster::stack(pathBios)
    crs(biosTotal)<-CRS("+proj=longlat +ellps=WGS84")
    
    cl<-makeCluster(numCores)
    clusterApply(cl,sp, MatCorrPAR2, biosTotal=biosTotal, results=results)
    stopCluster(cl)
    
    toc(log=T)
    
    time1<-as.data.frame(unlist(tic.log()))
    timeOK1<-separate(time1, 
                      col="unlist(tic.log())",
                      c("operacion", "tiempo_seg", "2"), sep=" sec |//: ") %>% 
      dplyr::select(-"2") %>% mutate(tiempo_seg = as.numeric(tiempo_seg),
                                    tiempo_min=ifelse(!is.na(tiempo_seg), tiempo_seg/60,NAS),
                                     tiempo_h=ifelse(!is.na(tiempo_min), tiempo_min/60, NA))
    write.csv(timeOK1, paste0(results, "/tiempos.csv"))
    

Issue

When running this code, I get the following error:

Error in checkForRemoteErrors(val) : 
  one node produced an error: Argumento NA/NaN

I’ve already tried the following without success:

Question

What could be causing this error? How can I better handle this issue when running the process in parallel?

Rversion: 4.2.2

Any help is greatly appreciated!

Upvotes: 0

Views: 18

Answers (1)

Robert Hijmans
Robert Hijmans

Reputation: 47481

I have a dataset (db) with 842 obs. of 45 variables

Can you use this example data set to illustrate your problem?

set.seed(221)
db <- matrix(runif(842*45), ncol=45)

Run the process in parallel to improve performance

Why, if this takes no time at all?

system.time(x <- cor(db))
#   user  system elapsed 
#      0       0       0 

Upvotes: 0

Related Questions