0

I’m looking for a short solution to create and use different tables in for loops where the loop variable is part of the name.

I found the following solutions:

If I want to create tables in a loop I may use assign together with paste. E.g.:

for (f in files){
assign(paste0("A_",f), readWorksheetFromFile(paste0(f,".xlsx")))}

And if I want to use these tables I may use eval, parse and paste0 in the following way:

for(f in files){
  x <- eval(parse(text=paste0("A_",f)))}

The problem is that I have to use these constructions very often and the code is getting very long. Does anyone has a shorter solution to do this in R?

E.g. in SAS I could use something like (as I remember)

x = A_&f;

instead of

x <- eval(parse(text=paste0("A_",f)))

Edit

Based on the following answers I found this solution:

In the process of creating objects in a loop I may use the function

`%c%` = function(a, b) paste0(a, b) 

in the following way for two or more strings:

"A_" %c% f 
"A_" %c% f %c% r

In case I want to use this object in a loop I can use the function:

`%u%` = function(a, b) eval(parse(text=paste0(a,b))) 

in the following way for two or more strings:

"A_" %u% f
"A_" %c% f %u% r

Notice that I used the %u% only in the last step.

Thomas R
  • 1,067
  • 11
  • 17

2 Answers2

1

You could try using a list:

l = vector("list", length(files))
names(l) = paste0("A_", files)
for(i in seq_along(files))
  l[[i]] = readWorksheetFromFile(paste0(files[i],".xlsx")))

If you need them to be separate variables, you could create your own environment and store them there:

myenv = new.env()
lapply(seq_along(l), function(i) assign(names(l)[i], l[[i]], pos = myenv))

And retrieve the variables using get:

vars = ls(pos = myenv)
get(vars[1], pos = myenv) 

EDIT

So really you're just looking for an operator like _&:

`%&%` = function(a, b) get(paste0(a, "_", b))

"A" %&% f

A = "A"
A %&% f
mikeck
  • 3,534
  • 1
  • 26
  • 39
  • Thanks. This might help in special situations. But it's not really shorter then my other solution. – Thomas R Nov 04 '16 at 10:23
  • That solution did not work in my case, but at least it was a great example. Based on your idea I created my final solution. See the edit of my original post. Thanks you helped me not just with this problem but to understand how to create functions in general. – Thomas R Nov 08 '16 at 11:03
0

That's what I usually do when I have to read many files in a batch:

l <- lapply(paste0(files,".xlsx"), readWorksheetFromFile)
names(l) <- paste0("A_", files)

No for loop required.

l is a list containing named data.frames. Use str(l) to exhibit the structure.

A single data.frame or table can be accessed in 3 different ways:

l[[1]]
l$A_File1
l[["A_File1"]]

Dummy data

To make this a reproducible example I created dummy data as follows:

set.seed(1234)
readWorksheetFromFile <- function(f) {
  n <- sample.int(5, 1)
  data.frame(a = sample.int(9, n), b = sample(LETTERS, n), 
             stringsAsFactors = FALSE)
}
files <- paste0("File", 1:5)
Uwe
  • 41,420
  • 11
  • 90
  • 134