开发者

For loop question in R

开发者 https://www.devze.com 2023-02-05 05:17 出处:网络
Hope I can explain my question well enough to obtain an answer - any help will be appreciated. I have a number if data files which I need to merge into one. I use a for loop to do this and add a colu

Hope I can explain my question well enough to obtain an answer - any help will be appreciated.

I have a number if data files which I need to merge into one. I use a for loop to do this and add a column which indicates which file it is.

In this case there are 6 files with up to 100 data entries in each.

When there are 6 files I have no problem in getting this to run.

But when there are less I have a problem.

What I would like to do is use the for loop to test for the files an开发者_运维技巧d use the for loop variable to assemble a vector which references the files that exist.

I can't seem to get the new variable to combine the new value of the for loop variable as it goes through the loop.

Here is the sample code I have written so far.

for ( rloop1 in 1 : 6) {
ReadFile=paste(rloop1,SampleName,"_",FileName,"_Stats.csv", sep="")
if (file.exists(ReadFile))
**files_found <- c(rloop1)**
}

What I am looking for is that files_found will contain those files where 1...6 are valid for the files found.

Regards Steve


It would probably be better to list the files you want to load, and then loop over that list to load them. list.files is your friend here. We can use a regular expression to list only those files that end in "_Stats.csv". For example, in my current working directory I have the following files:

$ ls | grep Stats
bar_Stats.csv
foobar_Stats.csv
foobar_Stats.csv.txt
foo_Stats.csv

Only three of them are csv files I want to load (the .txt file doesn't match the pattern you showed). We can get these file names using list.files():

> list.files(pattern = "_Stats.csv$")
[1] "bar_Stats.csv"    "foo_Stats.csv"    "foobar_Stats.csv"

You can then loop over that and read the files in. Something like:

fnames <- list.files(pattern = "_Stats.csv$")
for(i in seq_along(fnames)) {
    assign(paste("file_", i, sep = ""), read.csv(fnames[i]))
}

That will create a series of objects file_1, file_2, file_3 etc in the global workspace. If you want the files in a list, you could instead lapply over the fnames:

lapply(fnames, read.csv)

and if suitable, do.call might help combine the files from the list:

do.call(rbind, lapply(fnames, read.csv))


There's a much shorter way to do this using list.files() as Henrik showed. In case you're not familiar with regular expressions (see ?regex), you could do.

n <- 6
Fnames <- paste(1:n,SampleName,"_",FileName,"Stats.csv",sep="")
Filelist <- Fnames[file.exists(Fnames)]

which is perfectly equivalent. Both paste and file.exists are vectorized functions, so you better make use of that. There's no need for a for-loop whatsoever.

To get the number of the filenames (assuming that's the only digits), you can do:

gsub("^[:digit:]","", Filelist)

See also ?regex


I think there are better solutions (e.g., you could use list.files() to scan the folder and then loop over the length of the returned object), but this should (I didn't try it) do the trick (using your sample code):

files.found <- ""    
for (rloop1 in 1 : 6) {
    ReadFile=paste(rloop1,SampleName,"_",FileName,"_Stats.csv", sep="")
    if (file.exists(ReadFile)) files_found <- c(files.found, rloop1)
}

Alternatively, you could get the fileNames (other than their index) via:

files.found <- ""    
for (rloop1 in 1 : 6) {
    ReadFile=paste(rloop1,SampleName,"_",FileName,"_Stats.csv", sep="")
    if (file.exists(ReadFile)) files_found <- c(files.found, ReadFile)
}

Finally, in your case list.files could look something like this:

files.found <- list.files(pattern = "[[:digit:]]_SampleName_FileName_Stats.csv")
0

精彩评论

暂无评论...
验证码 换一张
取 消