-1

I have a problem processing filename as variable in a loop in R

files <- list.files(pattern = "*.tab",full.name=T)
for (a in files) { aname <- strsplit(basename(a), "\\.")[[1]][1]
                   aname <- read.table(a,header=TRUE, sep="\t",comment.char="")
                }

It produces only one object: aname, if I use following:

for (a in files) { c(strsplit(basename(a), "\\.")[[1]][1]) <- read.table(a,header=TRUE,
                        sep="\t",comment.char="")
                }

it produces: could not find function "c<-". But if I do

for (a in files) { aname <- strsplit(basename(a), "\\.")[[1]][1]
                   print(aname)
                }

The output is a list of files without extension, as expected. So, the question is: how do I make result of a function a variable name? Thank you!

Glen_b
  • 7,883
  • 2
  • 37
  • 48
John Amraph
  • 461
  • 6
  • 19
  • Assigning variable names on the fly has been discussed repeatedly on [so]. Try this for instance: http://stackoverflow.com/q/2679193/429846 – Gavin Simpson Nov 14 '12 at 21:59
  • Pardone my ignorance, but assign(strsplit(basename(a), "\\.")[[1]][1], read.table(a,header=TRUE, sep="\t",comment.char="")) doesnt work...Update: I solved it already. Thank you! – John Amraph Nov 14 '12 at 22:09

1 Answers1

6

The problem is not in processing the file name but in the way you've written the loop. Essentially you are doing:

for(i in list.of.files) {
  foo <- processName(i)
  foo <- read.table(foo)
}

when viewed like that, it is clear that foo gets written to twice for each iteration of the loop and hence can only ever take the value of the last read.table() call.

What you want to do is allocate storage for the list of files before you enter the loop, and then fill in that list as you go. For example:

aname <- vector("list", length = length(files))
fnames <- character(length(files))
for(i in seq_along(aname)) {
  fnames[i] <- strsplit(basename(files[i]), "\\.")[[1]][1]
  aname[i] <- read.table(a, header=TRUE, sep="\t", comment.char="")
}
names(aname) <- fnames

Having the objects contained in a list is a useful feature so you don;t have all those objects banging around. As they are contained within a list you can operate on each object using lapply() or similar.

If you really want to have an individual object that is has the filename without extension as its name for all files, then you could use assign(), but I don't recommend it

files <- list.files(pattern = "*.tab", full.name=TRUE)
for (a in files) {
  aname <- strsplit(basename(a), "\\.")[[1]][1]
  assign(aname, read.table(a, header=TRUE, sep="\t", comment.char="")
}

See ?assign for more.

Gavin Simpson
  • 170,508
  • 25
  • 396
  • 453
  • Thank you very much! for (a in files) { aname <- strsplit(basename(a), "\\.")[[1]][1] assign(aname, read.table(a, header=TRUE, sep="\t", comment.char="")) } --- work perfectly, I didn't know assign function. – John Amraph Nov 14 '12 at 22:12