-1

I have three data sets, relating to three scenarios (base, up, down): profile_base, profile_up, profile_down.

I have created a for loop for running some calculations in all 3 tables, and I need to adjust the name of a specific column at the end. The below doesn't work, giving an error:

target of assignment expands to non-language object

I tried the same with setNames.

for (i in c('base','up',’down’))) { 
colnames(get(paste0("profile_",i)))[2] <-  paste0("Probability_", i )
} 
massisenergy
  • 1,764
  • 3
  • 14
  • 25
A K
  • 1
  • 1
    You can't assign with `<-` to something you've retrieved using `get()`. You would need to use `assign()`. But in general that's not a great pattern to use in R. It's easier to help you if you include a simple [reproducible example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) with sample input and desired output that can be used to test and verify possible solutions. – MrFlick Dec 17 '18 at 18:00
  • Use lists of data frames (especially for similar structured objects) and then run your needed operations in loops or apply methods. – Parfait Dec 17 '18 at 19:43

1 Answers1

0

colnames<- is what is called a replacement function, which are well explained in the following answer in SO: What are Replacement Functions in R?

Closer to your example, consider the following code:

> colnames(data.frame(v1=1,v2=2))<-c("a", "b")
Error in colnames(data.frame(v1 = 1, v2 = 2)) <- c("a", "b") : 
  target of assignment expands to non-language object
> "colnames<-"(data.frame(v1=1,v2=2), c("a", "b"))
  a b
1 1 2

So if you really want to loop through a vector of object names (which I do not recommend, - a named list would be better for most cases), you can use the "colnames<-" syntax but not colnames(get(whatever))<-.... Assuming that your objects are data frames (not matrices), you might write a new function based on setNames, e.g., like this:

setSomeNames <- function(object=nm, i, nm){ names(object)[i] <- nm; object}
# to set only ith name, not all names
setSomeNames(data.frame(v1=1,v2=2), 2, "bang") 
# the second name is set to "bang"

... and the loop could work like this:

profile_base <- profile_up <- profile_down <- data.frame(v1=1,v2=2) # dummy data  
for (i in c('base','up','down')) { 
  foo <- paste0("profile_", i)
  assign(foo, setSomeNames(get(foo), 2, paste0("Probability_", i)))
} 

Alternatively, you could construct a call and then evaluate it. (Well, I'm not actually recommending doing it this way - in your case, three simple assignments would be the easiest solution, and then using a named list. But it might be instructive about how R works).

profile_base <- profile_up <- profile_down <- data.frame(v1=1,v2=2) # resetting the dummy data
for (i in c('base','up','down')) 
  eval(call("<-", call("[", call("colnames", as.name(paste0("profile_", i))), 2), paste0("Probability_", i)))

Finally, there is always the eval-parse approach which you can figure out on your own if you are so inclined:) e.g. Evaluate expression given as a string

lebatsnok
  • 6,329
  • 2
  • 21
  • 22