I could not find the previous question about this, but this one is pretty close.
Often I create new objects and want them to have the same dimnames ( names , colnames , rownames ) like some other object. Usually I would use names or rownames + colnames , but I'm tired of doing this, and I want a better solution. I also want a solution that allows partial overlap, so I need a new function. My problem is that it seems not quite easy to get it exactly.
Firstly, an auxiliary function:
get_dims = function(x) { if (is.null(dim(x))) { return(length(x)) } else { return(dim(x)) } }
This gets the size of any object. dim() returns NULL for atomic objects (vectors and lists), whereas it really should just return its length.
Then we compile some minimal test data:
t = matrix(1:9, nrow=3) t2 = t rownames(t) = LETTERS[1:3]; colnames(t) = letters[1:3]
Check:
> t abc A 1 4 7 B 2 5 8 C 3 6 9 > t2 [,1] [,2] [,3] [1,] 1 4 7 [2,] 2 5 8 [3,] 3 6 9
The test is that t2 should receive dimnames t . I print them because == apparently cannot handle list comparing (returns logical(0) ).
A simple solution is to take the object whose names I want to copy, the object into which I want to copy them, and simply change the dimnames in the function and return the object back. This can be done as follows:
copy_names1 = function(x, y, partialmatching = T) { #find object dimensions x_dims = get_dims(x) y_dims = get_dims(y) #set names if matching dims if (all(x_dims == y_dims)) { #loop over each dimension for (dim in 1:length(dimnames(x))) { dimnames(y)[[dim]] <- dimnames(x)[[dim]] } } return(y) }
Test:
> copy_names1(t, t2) abc A 1 4 7 B 2 5 8 C 3 6 9
Thus, it works fine, but returns an object, which means that you need to use the assignment operator, which is not needed with ordinary * names() functions.
We can also assign from a function using assign() :
copy_names2 = function(x, y, partialmatching = T) {
Test:
> copy_names2(t, t2) > t2 abc A 1 4 7 B 2 5 8 C 3 6 9
It also works: it does not require the use of an assignment operator and returns quietly. However, it copies the object to RAM (I think), which is bad when using large objects. It would be better to call dimnames on an existing object without copying it. Therefore, I try:
copy_names3 = function(x, y, partialmatching = T) {
Test:
> copy_names3(t, t2) Error in dimnames(get(y_obj_name, pos = -1))[[dim]] <- dimnames(x)[[dim]] : could not find function "get<-"
A very mysterious mistake! According to the previous question, get() cannot be used like that because it only retrieves values, not assigns them. Persons write instead of assign() . However, in the documentation for assign() we find:
assign does not send assignment methods, so it cannot be used to set vector elements, names, attributes, etc.
How to copy dimnames without copying objects using function?