I am a R beginner and I want to read multiple ASCII text files with the same name but located in different folders. I have a folder that contains other folders named after different species (e.g. spp1
). Inside each species folder, different there are folders for different models (e.g. model1
) and, inside that there are ASCII files with the same name (e.g. var1.asc
).
Example listing:
$ find path -type f
path/spp1/model1/var1.asc
path/spp1/model2/var1.asc
path/spp2/model1/var1.asc
path/spp2/model2/var1.asc
For each species, I need to read the ASCII files of all models it has and calculate the median of the values between models.
I tried first to create the file path for the spp1
, for example:
## Create a list file with the the species ##
setwd("mypath")
data <-list.files(pattern=".csv")
## Create the names of all the species by reading the files and deleting 4 characters (".csv") ##
for (i in 1:length(names)){
names <- substr(data[i],1,nchar(data[i])-4)
## Then i tried to read in loop the ascii files only saves me the last ascii, not a list of all ##
## Once i have the names i create all the paths for the species ##
path <- paste0("mypath", names)
## Then i create the subfolders for each model with and list that contains this names ##
path_m <- paste0(path, Model[i])
for (i in 1:length(names)){
models <- list.files(path_m,
pattern = ".asc",
full.names = TRUE)
stack <- raster::stack(models)}
## Calculate the median ##
median(models)
}
I would appreciate any help and thank you so much for your time.
Edit
The name variable it is defined here as:
names <- substr(data[i],1,nchar(data[i])-4)
The original code is (formatted by editor):
library(raster)
## crear un listado de los nombres de mis especies ##
BASEDIR <- "D:/7_Doctorado/Sceloporus/3_Models/kuenm"
data <- list.files(file.path(BASEDIR, "1_Joint"), pattern=".csv")
for (i in 1:length(data)) {
names <- substr(data[1], start=1, stop=nchar(data[1]) - 4)
path_cal <- file.path(BASEDIR, paste0("ResultCalibracion_", names))
setwd(path_cal)
cal_res <- read.csv("best_candidate_models_OR_AICc.csv")
row_names <- cal_res[, 1]
for (i in 1:length(row_names)) {
path <- file.path(BASEDIR,
paste0("Final_Models_", names),
paste0(row_names[i],"_NE"))
models <- list.files(path,
pattern = "M_median.asc",
full.names = TRUE)
stack <- raster::stack(models)
}
median_sp <- median(models)
sd_sp <- sd(models)
setwd(file.path(BASEDIR, "2_Models"))
writeRaster(median_sp, filename=paste0(names, "_median"), format="ascii")
writeRaster(sd_sp, filename=paste0(names, "_sd"), format="ascii")
}
It is hard to understand if you don't have the full context, that is why I prefer to explain the logic behind my question. The code above generates no errors, but the loop only reads the last ASCII file.
CodePudding user response:
I was editing your question (indenting and simplifying the code a bit to facilitate its reading) and maybe I found the error.
In the original code you added, the first statement of the outer loop reads:
names <- substr(data[1], start=1, stop=nchar(data[1]) - 4)
But it probably should use data[i]
(with a lower case letter i instead of a digit 1).
To avoid this kind of error, R allows iterating over vectors or lists directly, without the need of indexes. For example, the beginning of the loop:
for (i in 1:length(data)) {
names <- substr(data[i], start=1, stop=nchar(data[i]) - 4)
Could be rewritten as:
for (filename in data) {
names <- substr(filename, start=1, stop=nchar(filename) - 4)
Or even using a specialized function to remove the filename extension:
for (filename in data) {
names <- tools::file_path_sans_ext(filename)
# Or as you knew the extension ("$" marks end-of-string):
names <- sub('\\.asc$', '', filename)
Using these kinds of dialects prevents that types of lookalike character typos and off-by-one bugs that are common when using bare indices.