Using get() with replacement functions
Can anyone explain to me why the following example occurs?
#Create simple dataframe
assign( "df" , data.frame( P = runif(5) , Q = runif(5) , R = runif(5) ) )
#Return the dataframe from the given character vector
get( "df" )
P Q R
1 0.17396222 0.90994676 0.90590685
2 0.33860092 0.98078739 0.38058921
3 0.80751402 0.93229290 0.82853094
4 0.05460417 0.55448507 0.01605027
5 0.04250316 0.03808318 0.40678270
#Return the column names of df
colnames( get( "df" ) )
[1] "P" "Q" "R"
#But using a replacement function...
colnames( get( "df" ) ) <- c( "S" , "T" , "U" )
Error in colnames(get("df")) <- c("S", "T", "U") :
target of assignment expands to non-language object
I'd
A) like to know why the replacement functions won't work in this way with get()
?
And b) if there is some way to work around this, given my problem which I outline below;
My problem is that I have many objects, created (using a toy example) in a loop, something like this: assign( paste( "Object" , i , sep = "." ) , rnorm(1000 , i) )
, where i
is a vector, say i <- 1:1000
and then I would like to be able to assign names (for instance from a different vector) to each object in the loop, but names( get( paste( "Object" , i , sep = "." ) ) <- someNewName
doesn't work as in the example above.
But get( paste( "Object" , i , sep = "." ) )
does return the names (or NULL
) of those objects.
Thanks!
To understand why this doesn't work, you need to understand what colnames<-
does. Like every function in that looks like it's modifying an object, it's actually modifying a copy, so conceptually colnames(x) <- y
gets expanded to:
copy <- x
colnames(copy) <- y
x <- copy
which can be written a little more compactly if you call the replacement operator in the usual way:
x <- `colnames<-`(x, y)
So your example becomes
get("x") <- `colnames<-`(get("x"), y)
The right side is valid R, but the command as a whole is not, because you can't assign something to the result of a function:
x <- 1
get("x") <- 2
# Error in get("x") <- 2 :
# target of assignment expands to non-language object
Using assign
in the way you demonstrate in the question is at least uncommon in R. Normally you would just put all objects in a list.
So, instead of
for (i in 1:10) {
assign( paste( "Object" , i , sep = "." ) , rnorm(1000 , i) )}
you would do
objects <- list()
for (i in 1:10) {
objects[[i]] <- rnorm(1000 , i) }
In fact, this construct is so common that there is a (optimized) function (lapply
), which does something similar:
objects <- lapply(1:10, function(x) rnorm(1000,x))
You can then access, e.g., the first object as objects[[1]]
and there are several functions for working with lists.