Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Write a function that can work as `labels(x) <- some_value`

Tags:

methods

select

r

I want to write a function, labels, that works as follows:

x <- 1:6
labels(x)
# [1] 1 2 3 4 5 6

labels(x) <- 2:7
labels(x)
# [1] 2 3 4 5 6 7

labels(x)[1:2] <- 9:10
labels(x)
# [1] 9 10 4 5 6 7

How can I do so?

like image 395
Tal Galili Avatar asked Dec 28 '22 03:12

Tal Galili


1 Answers

What you seem to want is to understand replacement functions. If we look at names, we also note that there is a names<- function as well, with the following definition:

> `names<-`
function (x, value)  .Primitive("names<-")

Which isn't very informative about what it actually does, but shows that you can write any function of the form foo<- that replaces some components of the object the function is applied to.

x <- 1:6
X <- matrix(1:9, ncol = 3)

Labels <- function(obj, ...) {
    UseMethod("Labels")
}

Labels.numeric <- function(obj, ...) {
    names(obj)
}

Labels.matrix <- function(obj, which = c("colnames","rownames"), ...) {
    if(missing(which))
        which <- "colnames"
    which <- match.arg(which)
    if(which == "colnames") {
        out <- colnames(obj)
    } else {
        out <- rownames(obj)
    }
    out
}

`Labels<-` <- function(obj, ..., value) {
    UseMethod("Labels<-")
}

`Labels<-.numeric` <- function(obj, ..., value) {
    names(obj) <- value
    obj
}

Which can be used as follows:

> x <- 1:6
> Labels(x)
NULL
> Labels(x) <- LETTERS[1:6]
> x
A B C D E F 
1 2 3 4 5 6

A matrix method, might be:

`Labels<-.matrix` <- function(obj, which = c("colnames","rownames"), ..., value) {
    if(missing(which))
            which <- "colnames"
        which <- match.arg(which)
        if(which == "colnames") {
            colnames(obj) <- value
        } else {
            rownames(obj) <- value
        }
        obj
}

Which is used as:

> Labels(X)
NULL
> Labels(X) <- letters[1:3]
> X
     a b c
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
> Labels(X, which = "rownames") <- LETTERS[24:26]
> X
  a b c
X 1 4 7
Y 2 5 8
Z 3 6 9

The trick is to remember that replacement functions are called with a value argument that takes the values from the right hand side of <-, so your function definition needs to have a value argument, and use this argument to set/change the labels.

Of course, all this can be done using names, colnames etc, but if you want to understand how this works then hopefully the above is of use?

like image 161
Gavin Simpson Avatar answered Dec 30 '22 15:12

Gavin Simpson