Words and terms often seen in relation to the use of assign()
and get()
are dynamic object name and dynamic variable name. In other words, how do you assign a value to an object when the object name you must use can change, or is just one of many objects that you need to create in one go?
One of the first things you learn in R is how to assign values. For example, lets assign the value 100 to the object x, and then call x:
x <- 100
x
## [1] 100
That is all fine when you assign one value to one variable object with a known, static name.
However, sometimes you have a situation where you need to assign several different values to several different objects, and the object names themselves are available only as values of some other object.
Let’s say we have the object names A, B, C and they are stored as values in the vectors object my_names:
my_names <- c("A", "B", "C")
my_names
## [1] "A" "B" "C"
So far so good. Now, we also have an equal number of values that we would like to assign to objects with the names found in my_names:
my_values <- c("alfa", "bravo", "ceasar")
my_values
## [1] "alfa" "bravo" "ceasar"
So, we now want “alfa” to be the value of the object A and so on. How can we make that happen? Let’s try something.
my_names[1] <- my_values[1]
my_names
## [1] "alfa" "B" "C"
Not exactly what we had in mind… The value “alfa” simply replaced the value “A” in the vector my_names. No object A with value “alfa” was created.
The solution to this is the assign()
function:
assign(my_names[2], my_values[2])
B
## [1] "bravo"
So, With assign()
, we are able to assign a value to an object, while specifying the object name as being the value of another object - in this case, value nr 2 in the my_names vector!
The assign()
function is also great when you have names of objects in one vector, and values in another vector, since it allows you to write DRY code and loop over the vectors (which are assumed to match by position). Instead of just a value, you can also put function call as the value argument in assign()
:
object_names <- sample(LETTERS, 5)
object_names
## [1] "T" "C" "R" "M" "X"
object_values <- sample(c(1:9), 5)
object_values
## [1] 6 8 3 4 1
doubleit <- function(x) {x*2} # a small example function
for (i in c(1:length(object_names) )) { assign(object_names[i], doubleit(object_values[i]) ) }
Now, the real value of the above comes for example in situations where you have object names that are pulled from some source by following some criteria, and the object names will change form one time to the next. And likewise, the values are created from some source by some rules but the values don’t stay the same between runs - maybe because the values depend on the the thing that decides the object names.
So what if we want to inspect the objects created and their values? How can we “call” them? Again, let’s try something:
object_names[1]
## [1] "T"
Er, no. That will only return the first one of the object names stored in object_names. It will not call the actual object carrying that name.
What we need here is the twin of assign()
which is get()
:
for (i in c(1:length(object_names)) ) { object <- get(object_names[i]); print(object) }
## [1] 12
## [1] 16
## [1] 6
## [1] 8
## [1] 2
Ta-da! get()
lets you call an object by specifying the object name as being the value of some other object, such as the value at a particular index position in the object_names
vector.
You can also use the call to get()
as an argument to a function. Let’s use the function typeof()
for a quick example:
for (i in c(1:length(object_names)) ) { object <- typeof(get(object_names[i]) ); print(object) }
## [1] "double"
## [1] "double"
## [1] "double"
## [1] "double"
## [1] "double"
Obviously, the function for which the get()
call is used as an argument can be any function that you have.