R loop to create multiple objects from equally as many existing objects - r

I've tried searching for the answer to this but am having trouble because I'm not sure I'm even searching the right thing. Basically I would like in R to create a loop to create multiple objects, each from a different object. For example, let's say I have 50 existing objects (matrix, data frame, graph etc.) and they are all named similarly (table1, table2...table50). Now I would like to create 50 new objects, lets say graph1...graph50. I'm having trouble with a loop because I don't know how to work with the names being strings. I've tried the assign function, but it isn't dynamic enough in the assignment argument. I would basically like something like this:
for (i in list(table names)){
graph "i" <- as.network(table "i")
}
I would also like to have this hold for objects assigned as some function of itself ie graph "i" <- somefunction(graph "i") etc...
Additionally if there is a more efficient way by all means I'm open to it. It seems like an easy task but I can't figure it out. Right now I'm literally just concatenating the statements in excel and pasting to R so it doesn't take too long, but it is a pain. Thank you.

I think you could have a nested loop to do what you're looking for; you could could apply whatever transformations you're wanting to each object within the input list and store the results in a new list with the same object names.
in_list <- list(table1 = iris,
table2 = EuStockMarkets)
out_list <- list()
for(i in 1:length(in_list)){
for(j in colnames(in_list[[i]])){
out_list[[ gsub("table", "graph", names(in_list)[i]) ]][[j]] <- summary(in_list[[i]][,j])
}
}
Hope this helps!

Related

How to reference a dynamically assigned dataframe name

I have successfully allocated dataframe names and populated them (see code) but I do not know how to subsequently reference them. So I loop through to assign df.test1 and populate it with some data 1 and so on. I know that the df has been created, and can view or summary it in the console, but not in the code.
I am pretty new to R so am not sure if some of the solutions I have looked at apply to me.
num.clusters <- 5
for (i in 1:num.clusters) {
assign(paste("df.test",i,sep=""), paste("somedata", i))
}
This works but Then want to do something like:
View(df.test,i)
to view whatever iteration from 1 to 5.
I want to be able to use the assigned dataframes like any other dataframe. I could hard code this as View(df.test1) but that would defeat the point. I also want to do other things with the datframe, e.g. subsetting.
I know this doesn't work. Would love to know what does.
Many thanks...
Your question is the proof that the approach is problematic: avoid using assign in general because it makes accessing the variables afterwards awkward (among other issues).
A cleaner way is to just put your "data frames" (copying from your example) in a list:
num.clusters <- 5
df.test <- list()
for (i in 1:num.clusters) {
df.test[[i]] <- paste("somedata", i)
}
Then you would just access them like this:
View(df.test[[i]])
If what you put in there was an actual data.frame (and not the strings you were using), you could then access its columns like any other data.frame:
df.test[[i]]$Name
Or
df.test[[i]][, "Name"]

Name new dataframes from character vectors - loop

I think this one is easy but I still can't figure it out and I really need help with this. I've looked everywhere but still couldn't find it.
Let's say I have this vector:
filenames <- c("fn1", "fn2", "fn3")
And I want to associate them with an dataframe that is created according to a function, that is generated at that time
df|name from filenames[i]| <- df
so it would return these dataframes
dffn1
dffn2
dffn3
I hope I made myself clear. My problem is create a new data frame and name it according to a list or whatever, in a for loop.
You can use assign to achieve what you want.
for(nms in filenames){
assign(paste('df',nms,sep=''), df) }

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.
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.
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.

Getting nested elements from a list

I am trying to get nested elements from a list. I can extract the elements using: unlist(pull_lists[[i]]$content[[n]]['sha']), however, it seems that I cannot insert them in a nested list. I have extracted a single element of the list in a gist, which creates the reproducible example below. Here is what I have so far:
library("devtools")
pull_lists <- list(source_gist("669dfeccad88cd4348f7"))
sha_list <- list()
for (i in length(pull_lists)){
for (n in length(pull_lists[[i]]$content)){
sha_list[i][n] <- unlist(pull_lists[[i]]$content[[n]]['sha'])
}
}
How can I insert the elements in a nested fashion?
When I download the content, I get a much more complicated structure than you do. For me, it's not pull_lists[[i]]$content, it's pull_lists[[i]]$value$content[[1 or 2]]$parents$sha. The reason nothing is populating is because there is nothing there to populate (ie, n = 0).
I've had to deal with similar data structures before. What I found was that it's much easier to search the naming structure after unlisting rather than to figure out the correct sequence of subsets.
Here's an example:
sha_locations <- grep("sha$",names(unlist(pull_list[[1]])))
unlist(pull_list[[1]])[sha_locations]
Cleaning the for loop a bit, this would look like:
sha_list <- lapply(
pull_list,
function(x) unlist(x)[grep("sha$",names(unlist(x)))]
)
Since there are multiple SHAs, and the question only asks for the SHAs at specific positions, you need to extract those SHAs:
sha_list <- sha_list[[1]][attr(sha_list[[1]], "names")=="value.content.sha"]

R: calling function on multiple list entries

I'm really new to R but have a computer science background. I currently am trying to read in a bunch of different data files and then perform some analysis (the same) on each of them.
Right now, I have a list of datasets. So, my first data set is in list[[1]], second in list[[2]], etc. So, what I was going to do is loop on the length of the list and call some function passing values from two columns into that function from each unique dataset. I was reading an article on this, however, and found that:
foo = seq(1, 100, by=2)
foo.squared = NULL
foo.squared = foo^2
will square all the values within foo. So, is there any way to do something similar for my case? For example, passing in values from all the datasets in the list or something?
To make this more concrete, I have a list of datasets named data_list and each data set is identical with columns a, b and c. I need to call a function f with the arguments a and b from the datasets. Is there any way to do this besides using a for loop?
Please let me know if that makes sense. Sorry for any confusion, like I said, I am very new to this language. Thank you for your help!
Use this:
lapply(data_list, function(x) f(x$a, x$b))

Resources