0

I'm having some trouble calling an object from a list, from a created variable within my for loop.

for (i in 1:10)
{
#create variables and run through function
varName<-paste("var",i,sep="")
assign(varName, rnmf(data, k=i, showprogress=FALSE))

#create new variable using object 3 from varName output
varNF<-paste("varNF",i,sep="")
assign(varNF, (data-varName[[3]])^2)
}

My problem is with the second part of my for loop. I am attempting to use the third object from the output of my first created variable, in the calculation of my second variable. If I use varName[[3]] I get "subscript out of bounds", and if I use varName$fit, I get "$ operator is invalid for atomic vectors".

It looks like varName in my second part is not calling the incrementing varName (var1, var2, var3, etc...) that I am creating, but it is calling the actual variable varName. To try and get around that, I instead tried

assign(varNF, (data-get(paste("var",i,"[[3]]",sep="")))^2)

Which gave me the error "object 'var1[[3]]' not found". But, if I simply call var1[[3]] in my R console, it does exist. I'm not quite sure where to go from here. Any help would be great!

coderX
  • 424
  • 5
  • 16
  • 1
    I think you're looking for `get`, but the usage of `assign` in a `for` loop makes me wince. There are better ways, if you give some context. – alistaire Mar 26 '17 at 19:21
  • Basically, I have about 200 variables that I need to create and send through my function. Within each one of those newly created variables is a list of objects, in which I need to use one (the third) to create another new variable. The only problem I'm having is calling the object from the list of objects within the first new variable – coderX Mar 26 '17 at 19:39
  • 1
    `varName` stores a single string here that is the name of the variable, so if you call it, you're getting that string (`"var1"`), not the variable `var1`. To do that, you'd need `get(varName)[[3]]`. This is still a bad approach, though; it's better to structure your data in a single data.frame or list so it's inherently iterable. Moreover, grouping and reshaping will make a lot of iteration irrelevant, anyway. – alistaire Mar 26 '17 at 19:47
  • I'm not sure why this isn't a good approach though. Is there an easier/better way to create a large amount of variables, and run each one through my function other than for loop? It's doing exactly what I need in a matter of 2 lines of code. – coderX Mar 26 '17 at 19:53
  • You'll quickly discover that `for` loops (at least when not preallocated) are slow in R. They're not very easy to read, either, leading to problems like the one you've got. `assign` is a very powerful function, but one that should be avoided most of the time, as unless you're deliberately operating on the language (which most people rarely do) it's a sign that your code is not well-structured. – alistaire Mar 26 '17 at 20:13
  • Interesting. Appreciate the information. I did attempt get(varName)[[3]] and and still getting the "object not found" error. – coderX Mar 26 '17 at 20:23
  • To debug any further you'd need [to provide some data](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example#5963610). – alistaire Mar 26 '17 at 20:28

1 Answers1

1

A very useful rule of thumb in R is:

If you find yourself using either assign() or get() in your code, it's a strong indicator that you are approaching the problem with the wrong tools. If you still think you should use those functions, think again. The tools that you are missing are most likely R lists and subsetting of lists.

(and tell everyone that you know about the above)

In your case, I would do something like:

library("rNMF")
[...]

var <- list()
varNF <- list()
for (i in 1:10) {
    res <- rnmf(data, k = i, showprogress = FALSE)
    var[[i]] <- res
    varNF[[i]] <- (data - res$fit)^2
}
HenrikB
  • 6,132
  • 31
  • 34