I have 14 raster files in Tiff format and I want to read values of a series of pixels (same file location). However, when I ran the R code, the expected results did not show up. Could you tell me why?
#set working directory#
path <- 'E:/TSL_VCF/Tiffs'
setwd(path)
#list tiff files in the working directory#
list.files(path, pattern = 'tif')
#count the number of tiff files#
mylist <- list.files(path, pattern = 'tif')
mylength <- length(mylist)
#get values for certain "location"#
for (i in 1:mylength){
myraster <- raster(mylist[i])
mymatrix <- as.matrix(myraster)
mymatrix[1,771]
}
results are not printed because the instruction
mymatrix[1,771]
is inside the "for" loop. This:
#set working directory#
path <- 'E:/TSL_VCF/Tiffs'
setwd(path)
#list tiff files in the working directory#
list.files(path, pattern = 'tif')
#count the number of tiff files#
mylist <- list.files(path, pattern = 'tif')
mylength <- length(mylist)
#get values for certain "location"#
for (i in 1:mylength){
myraster <- raster(mylist[i])
mymatrix <- as.matrix(myraster)
print(mymatrix[1,771])
}
should work.
However, it won't store your resulting array anywhere but on the screen.
I'd suggest you to have a look at the extract function of the raster package for a better solution. If you build a rasterstack in advance using something like:
mystack <- stack(mylist)
you can also avoid looping over the files and just do something like:
result <- extract(mystack, as.matrix(c(1,771), nrow = 1))
, and you should get the results in the "result" variable
HTH,
Lorenzo
HTH,
Lorenzo
You need to explicitly call print if you want R to print stuff in a loop. For example:
m = rnorm(10)
for (i in 1:10) m[i] # doesn't print
for (i in 1:10) print(m[i]) # print
Related
I'm reading multiple Excel files and sheets within those files in loops. A certain range should be read from those sheets and added to a dataframe, corresponding to each file.
With the code I have written so far I can read the files and sheets and put them into a dataframe. However, it gives me the following error when specifying the range:
Error in as.cell_limits.character(range) : length(x) == 1L is not TRUE
path <- "my file path"
files_list <- list.files(path, pattern="*.xlsx", full.names = TRUE)
files_list_names <- str_extract(list.files(path, pattern="*.xlsx"),"[^.]+") ###extract filename without file extension
count_files <- length(files_list_names)
for (i in 1:count_files){
current_file <- files_list_names[i]
current_file_data <- read_excel(files_list[i], range="B22:B30")
this_file_sheets <- excel_sheets(files_list[i])
count_sheets <- length(this_file_sheets)
for (j in 1:count_sheets){
current_sheet_data <- read_excel(files_list[i],sheet = this_file_sheets[j],range("F22:F30"))
bind_cols(current_file_data,current_sheet_data)
}
assign(paste0(current_file),current_file_data,envir = .GlobalEnv)
}
I have absolutely no clue what that error means and I can't find anything on the web.
As always, your help is much appreciated!
Be sure to use range=, rather than range() when you call readxl::read_excel(). The latter will be invoking base::range() function. When you pass a string to base::range(), you get a vector of length 2 like this:
base::range("B22:B30")
[1] "B22:B30" "B22:B30"
If that vector of length 2 is passed to the range parameter of the read_excel() function, you will get the above error.
I have written code that runs sampling functions on a csv files for a biome.
I have 30 csv files that I want to loops these for loops over. I am struggling with applying this code I've written easily across all files in my folder. I'm sure this is an easy fix, I'm just finding issue with the loop inside of a loop.
temp <- read.csv("tropical_grassland_N_Am_point_summary_table_gdrive.csv")
temp <- temp[which(temp$nd > 0.1),]
index <- substr(temp[,5],30,(nchar(as.character(temp[,5]))-2))
unique_index <- unique(index)
unique_index <- sample(unique_index, 20, replace=F)
for (i in 1:length(unique_index)){
temp2 <- temp[which(index==unique_index[i]),]
theDates = strptime(temp2[,2], format="%Y-%m-%d")
}
thresh <- 0.95
for (i in 1:length(unique_index)){
temp2 <- temp[which(index==unique_index[i]),]
theDates = strptime(temp2[,2], format="%Y-%m-%d")
}
All of the csv files have _point_summary_table_gdrive.csv in common after the description of the continent and biome.
Are they in the same folder without other files ? if so, if your code works, you don't need to know the file names. just make a function of it and then
filenames <- list.files(path = whatyouwant, pattern = "*\\.csv$", all.files = TRUE,full.names = TRUE, recursive = TRUE)
files <- lapply(filenames,read.csv)
lapply(files,yourfunction)
I have for-loop listing multiple excel sheets , reading them, doing some processing and ideally I would like to store the resulting outputs into the same excel file/sheet.
the desired output is qs
files <- list.files(path = "V:/_190718AA_ascii", pattern =
"*.xlsx", full.names = T)
df.list <- lapply(files, read_excel,col_names=FALSE)
kClusters=5
for (m in df.list) {
qs[m]<- quantile(m[px[,,1,1]],probs=c(0,0.025,0.05,0.1,0.25,0.5,0.75,0.9,0.95,0.975,1))
write.xlsx(qs[m],"V:/_ORG/080-DOZP/BO-P2/DOZPLL/Esma/uqs.xlsx",sheet=m)
m <- m+1
}
it gives only the result from one m instead of 4.
m is not a number in your loop, but a dataframe. Additionnally, you do not need to increment it within a for loop.
My suggestion is to define m as number that will be incremented by the for loop. Not sure what is qs, so I've replaced it by a temporary variable (temp) for the sake of the example. But I haven't been able to test it as I do not have access to your data.
for (m in 1:length(df.list)) {
temp<- quantile(df.list[[m]][px[,,1,1]],probs=c(0,0.025,0.05,0.1,0.25,0.5,0.75,0.9,0.95,0.975,1))
write.xlsx(temp,"V:/_ORG/080-DOZP/BO-P2/DOZPLL/Esma/uqs.xlsx",sheet=m)
}
I have a list of files like:
nE_pT_sbj01_e2_2.csv,
nE_pT_sbj02_e2_2.csv,
nE_pT_sbj04_e2_2.csv,
nE_pT_sbj05_e2_2.csv,
nE_pT_sbj09_e2_2.csv,
nE_pT_sbj10_e2_2.csv
As you can see, the name of the files is the same with the exception of 'sbj' (the number of the subject) which is not consecutive.
I need to run a for loop, but I would like to retain the original number of the subject. How to do this?
I assume I need to replace length(file) with something that keeps the original number of the subject, but not sure how to do it.
setwd("/path")
file = list.files(pattern="\\.csv$")
for(i in 1:length(file)){
data=read.table(file[i],header=TRUE,sep=",",row.names=NULL)
source("functionE.R")
Output = paste("e_sbj", i, "_e2.Rdata")
save.image(Output)
}
The code above gives me as output:
e_sbj1_e2.Rdata,e_sbj2_e2.Rdata,e_sbj3_e2.Rdata,
e_sbj4_e2.Rdata,e_sbj5_e2.Rdata,e_sbj6_e2.Rdata.
Instead, I would like to obtain:
e_sbj01_e2.Rdata,e_sbj02_e2.Rdata,e_sbj04_e2.Rdata,
e_sbj05_e2.Rdata,e_sbj09_e2.Rdata,e_sbj10_e2.Rdata.
Drop the extension "csv", then add "Rdata", and use filenames in the loop, for example:
myFiles <- list.files(pattern = "\\.csv$")
for(i in myFiles){
myDf <- read.csv(i)
outputFile <- paste0(tools::file_path_sans_ext(i), ".Rdata")
outputFile <- gsub("nE_pT_", "e_", outputFile, fixed = TRUE)
save(myDf, file = outputFile)
}
Note: I changed your variable names, try to avoid using function names as a variable name.
If you use regular expressions and sprintf (or paste0), you can do it easily without a loop:
fls <- c('nE_pT_sbj01_e2_2.csv', 'nE_pT_sbj02_e2_2.csv', 'nE_pT_sbj04_e2_2.csv', 'nE_pT_sbj05_e2_2.csv', 'nE_pT_sbj09_e2_2.csv', 'nE_pT_sbj10_e2_2.csv')
sprintf('e_%s_e2.Rdata',regmatches(fls,regexpr('sbj\\d{2}',fls)))
[1] "e_sbj01_e2.Rdata" "e_sbj02_e2.Rdata" "e_sbj04_e2.Rdata" "e_sbj05_e2.Rdata" "e_sbj09_e2.Rdata" "e_sbj10_e2.Rdata"
You can easily feed the vector to a function (if possible) or feed the function to the vector with sapply or lapply
fls_new <- sprintf('e_%s_e2.Rdata',regmatches(fls,regexpr('sbj\\d{2}',fls)))
res <- lapply(fls_new,function(x) yourfunction(x))
If I understood correctly, you only change extension from .csv to .Rdata, remove last "_2" and change prefix from "nE_pT" to "e". If yes, this should work:
Output = sub("_2.csv", ".Rdata", sub("nE_pT, "e", file[i]))
I have several files in a directory. I can read them like this:
files <- list.files("C:\\New folder", "*.bin",full.names=TRUE)
for (i in 1:length(files)) {
conne <- file(files[i], "rb")
file <- readBin(conne, double(), size=4, n=300*700, signed=TRUE)
file2 <- matrix(data=file,ncol=700,nrow=300)
}
I wonder how can I put all the matrices (file2) as a list?
For instance:
m1<-matrix(nrow=4,ncol=2,data=runif(8))
m2<-matrix(nrow=4,ncol=2,data=runif(8))
I put them in a list as:
ml <- list(m1, m2)
In addition to akrun's answer, you could also just put them in a list to begin with by taking advantage of the lapply function. Modifying your code just slightly, it would look like this:
files <- list.files("C:\\New folder", "*.bin",full.names=TRUE)
dat <- lapply(1:length(files), function(i) {
conne <- file(files[i], "rb")
file <- readBin(conne, double(), size=4, n=300*700, signed=TRUE)
file2 <- matrix(data=file,ncol=700,nrow=300)
close(conne) # as indicated in the comments below
return(file2)
})
dat is now a list of all of your matrices. lapply acts as a loop, much like for, and will pass each iteration of its first argument, here 1:length(files), to the function as a parameter. The returned value it gets from the function will be passed to the list called dat as its own element.
Assuming that the OP created objects 'm1', 'm2' etc in the global envrironment, we can use mget to get the values of the object in a list by specifying the pattern argument in the ls as 'm' followed by numbers (\\d+).
mget(ls(pattern='m\\d+'))
If the question is to split up a large matrix into chunks
n <- 4
lapply(split(seq_len(nrow(m)),
as.numeric(gl(nrow(m), n, nrow(m)))), function(i) m[i,])