NDD
NDD

Reputation: 64

How to make loops in R that operate on and return multiple objects

This is my first post, and I think I have looked thoroughly for my answer with no luck, but I might not be typing in the right search terms, since I am relatively new to R. I apologize if this has been answered before and if it has a link would be greatly appreciated.

In essence, I am trying to make a loop that will operate on a set of data frames that I have read into R from .txt files using read.table. I am working with simulated vegetation data organized into many species by site matrices, so it would be best for me if I could create loops that will just operate on the objects I have read in using some functions I have made and then put out new objects into my workspace with a specific naming pattern (e.g. put "_av" on the end of the name of the object operated on when creating a new object).

for convenience sake, lets say I have only four matrices I want to work with, all which contain the phrase "mod" for model. I have read that I can put these data frames into a list of data frames by the following code:

    list.mods=lapply(ls(pattern="mod"),get)

This does create a list which I have been having trouble on getting my functions to actually operate on. From what I read this is the best way to make a list of objects you want to operate on.

So lets say that list.mods is now my list of operable matrices - mod1, mod2, mod3, and mod4. Also, lets say I have a function that simply calculates Bray-Curtis dissimilarity as follows:

    bc=function(x){
    vegdist(x,method="bray")
    }

I can use this by typing in:

    mod1.bc=bc(mod1)

That works. But it seems like I should be able to apply my list of models to the function bc and have it output the models with a pattern mod1.bc, mod2.bc, mod3.bc, and mod4.bc. I cannot get my list of files to work in the function much less save each operation as a new object with a patterned name.

What am I doing wrong? In the end I might have as many as a hundred models or more and would really appreciate being able to create a list of items that I can run through loops.

Thanks in advance.

Upvotes: 0

Views: 1762

Answers (2)

adatum
adatum

Reputation: 705

How about collecting the names of the models/objects you want into a list:

mod_list <- sapply(ls(pattern = "mod"), as.name)

and then looping over them with your function:

output_list <- lapply(eval(mod_list), bc)

With this approach you avoid creating the potentially large and redundant list.mods object in your example. Also, I think this will result in conveniently named lists.

Upvotes: 1

Luis
Luis

Reputation: 511

You can use lapply again:

new.list.mods <- lapply(list.mods, bc)

This will return a new list in which each element is the result of applying bc to the corresponding element of list.mods.

The 'apply' family of functions in R basically allows you to save typing. If that's easier for you to understand, you can use a 'for loop' instead. Of course you will need to know how to access elements in a list for that. There is a question about that.

Upvotes: 2

Related Questions