Search code examples
rvectorattributessubsetpersistent

subset() drops attributes on vectors; how to maintain/persist them?


Let's say I have a vector where I've set a few attributes:

vec <- sample(50:100,1000, replace=TRUE)
attr(vec, "someattr") <- "Hello World"

When I subset the vector, the attributes are dropped. For example:

tmp.vec <- vec[which(vec > 80)]
attributes(tmp.vec) # Now NULL

Is there a way to, subset and persist attributes without having to save them to another temporary object?

Bonus: Where would one find documentation of this behaviour?


Solution

  • I would write a method for [ or subset() (depending on how you are subsetting) and arrange for that to preserve the attributes. That would need a "class" attribute also adding to your vector so that dispatch occurs.

    vec <- 1:10
    attr(vec, "someattr") <- "Hello World"
    class(vec) <- "foo"
    

    At this point, subsetting removes attributes:

    > vec[1:5]
    [1] 1 2 3 4 5
    

    If we add a method [.foo we can preserve the attributes:

    `[.foo` <- function(x, i, ...) {
        attrs <- attributes(x)
        out <- unclass(x)
        out <- out[i]
        attributes(out) <- attrs
        out
    }
    

    Now the desired behaviour is preserved

    > vec[1:5]
    [1] 1 2 3 4 5
    attr(,"someattr")
    [1] "Hello World"
    attr(,"class")
    [1] "foo"
    

    And the answer to the bonus question:

    From ?"[" in the details section:

    Subsetting (except by an empty index) will drop all attributes except names, dim and dimnames.