4

Apparently, indexing a list with attributes returns a list without the attributes.

> l <- list(a=1:3, b=7)
> attr(l, 'x') <- 67
> l
$a
[1] 1 2 3

$b
[1] 7

attr(,"x")
[1] 67
> l[c('a','b')]
$a
[1] 1 2 3

$b
[1] 7

Attributes are gone. Is it possible to index a list while preserving its attributes?

Ernest A
  • 7,526
  • 8
  • 34
  • 40

2 Answers2

4

Here is such a subset function. Note that it is important to not try to overwrite the 'names' attribute.

subset.with.attributes <- function(X, ...) {
 l <- X[...]
 attr.names <- names(attributes(X))
 attr.names <- attr.names[attr.names != 'names']
 attributes(l)[attr.names] <- attributes(X)[attr.names]
 return(l)
}

> subset.with.attributes(l, c('a','b'))
$a
[1] 1 2 3

$b
[1] 7

attr(,"x")
[1] 67

Trying to simply assign the attributes will result in the subset failing if it actually does any subsetting.

> subset.with.attributes(l, c('b'))
$b
[1] 7

attr(,"x")
[1] 67
Matthew Lundberg
  • 42,009
  • 6
  • 90
  • 112
1

Use the sticky package. It was designed exactly for this purpose. (Full Disclosure: I am the package author.) It's simple to use, just call sticky() on your vector/list/etc. For example:

> l <- list(a=1:3, b=7)
> attr(l, 'x') <- 67    
> l <- sticky(l) 
> attr(l,'x')  
> [1] 67
>
> class(l)
> [1] "sticky" "list" 
ctbrown
  • 2,271
  • 17
  • 24