DarrenRhodes
DarrenRhodes

Reputation: 1503

Pasting in a for loop

I have a number of data.frames that I want to export to Excel using the package XLConnect. I'm doing this using a for loop, within the loop there is a paste function that gives the sheet name but I don't know how to construct the data name.

Here's what I mean.

My data.frames are named as follows,

port.1a, port.1b, port.2a, port.2b ... port.10a, port.10b

So far my code looks like this,

library(XLConnect)
for (i in 1:10){
    a[i]  <- paste("port.",i,"a",sep="")
    b[i]  <- paste("port.",i,"a",sep="")
    writeWorksheetToFile("wfe_bx3.xlsx", data=b[i], sheet=a[i])
}

I haven't bother with the port.1b data.frames as yet because I'm having difficulty with this part. Obviously, paste returns a character rather than a data.frame for data=b but cat doesn't work either.

Any help would be appreciated, if only to tell me that this is a repeat question. (There are lots of similar questions but they haven't helped).

Upvotes: 0

Views: 2651

Answers (2)

Martin Studer
Martin Studer

Reputation: 2321

As already suggested by @Gregor, ideally your objects would already be in a list. But here is a possible solution to your problem:

## Reproducing use case ##

# Names of data.frames
obj.names = do.call("paste0", expand.grid("port.", 1:10, c("a", "b")))
# Create dummy objects
sapply(obj.names, assign, mtcars, envir = globalenv())


## Solution ##

# Gather objects in a list
objs = lapply(obj.names, get)

require(XLConnect)
writeWorksheetToFile("wfe_bx3.xlsx", data = objs, sheet = obj.names)
# NOTE: Many functions in XLConnect are vectorized!

Upvotes: 1

Gregor Thomas
Gregor Thomas

Reputation: 145755

This ought to work. There's no real reason to make a and b length-10 vectors unless you want to use them afterwards.

for (i in 1:10){
    a  <- paste0("port.", i, "a")
    b  <- paste0("port.", i, "a")
    writeWorksheetToFile("wfe_bx3.xlsx", data = as.name(b), sheet = a)
}

I copy/pasted the code from your question, which doesn't seem to use the "b" files at all (you have "a" in both your pastes). Thus, a and b are identical in your loop and you really only need one.

Alternatively you could build the names first

a <- paste0("port.", 1:10, "a")
b <- paste0("port.", 1:10, "b") # assuming you wanted a "b" in here
for (i in 1:10){
    writeWorksheetToFile("wfe_bx3.xlsx", data = as.name(b[i]), sheet = a[i])
}

This is probably very slightly more efficient, definitely negligible in this use case.

One of the advantages of doing things in a list (as per my comment above) is that you don't have to worry about getting passing a string to a function expecting a data.frame. Let's say your data.frames are in two 10-element lists, porta and portb. Then something like this would be the easiest solution of all:

 for (i in 1:10){
        writeWorksheetToFile("wfe_bx3.xlsx", data = portb[[i]], sheet = names(portb)[i])
    }

Upvotes: 1

Related Questions