R: Allow Re-Listing an unlist()ed Object

relist {utils} | R Documentation

## Allow Re-Listing an unlist()ed Object

### Description

`relist()` is an S3 generic function with a few methods in order to allow easy inversion of `unlist(obj)` when that is used with an object `obj` of (S3) class `"relistable"`.

### Usage

    relist(flesh, skeleton)
    ## Default S3 method:
    relist(flesh, skeleton = attr(flesh, "skeleton"))
    ## S3 method for class 'factor'
    relist(flesh, skeleton = attr(flesh, "skeleton"))
    ## S3 method for class 'list'
    relist(flesh, skeleton = attr(flesh, "skeleton"))
    ## S3 method for class 'matrix'
    relist(flesh, skeleton = attr(flesh, "skeleton"))

    as.relistable(x)
    is.relistable(x)

    ## S3 method for class 'relistable'
    unlist(x, recursive = TRUE, use.names = TRUE)

### Arguments

`flesh` | a vector to be relisted
`skeleton` | a list, the structure of which determines the structure of the result
`x` | an R object, typically a list (or vector).
`recursive` | logical. Should unlisting be applied to list components of `x`?
`use.names` | logical. Should names be preserved?

### Details

Some functions need many parameters, which are most easily represented in complex structures, e.g., nested lists. Unfortunately, many mathematical functions in R, including `optim` and `nlm` can only operate on functions whose domain is a vector. R has `unlist()` to convert nested list objects into a vector representation. `relist()`, its methods and the functionality mentioned here provide the inverse operation to convert vectors back to the convenient structural representation. This allows structured functions (such as `optim()`) to have simple mathematical interfaces.

For example, a likelihood function for a multivariate normal model needs a variance-covariance matrix and a mean vector. It would be most convenient to represent it as a list containing a vector and a matrix. A typical parameter might look like

          list(mean = c(0, 1), vcov = cbind(c(1, 1), c(1, 0))).

However, `optim` cannot operate on functions that take lists as input; it only likes numeric vectors. The solution is conversion. Given a function `mvdnorm(x, mean, vcov, log = FALSE)` which computes the required probability density, then

            ipar <- list(mean = c(0, 1), vcov = c bind(c(1, 1), c(1, 0)))
            initial.param <- as.relistable(ipar)

            ll <- function(param.vector)
            {
               param <- relist(param.vector, skeleton = ipar)
               -sum(mvdnorm(x, mean = param$mean, vcov = param$vcov,
                            log = TRUE))
            }

            optim(unlist(initial.param), ll)

`relist` takes two parameters: skeleton and flesh. Skeleton is a sample object that has the right `shape` but the wrong content. `flesh` is a vector with the right content but the wrong shape. Invoking

        relist(flesh, skeleton)

will put the content of flesh on the skeleton. You don't need to specify skeleton explicitly if the skeleton is stored as an attribute inside flesh. In particular, if flesh was created from some object obj with `unlist(as.relistable(obj))` then the skeleton attribute is automatically set. (Note that this does not apply to the example here, as `optim` is creating a new vector to pass to `ll` and not its `par` argument.)

As long as `skeleton` has the right shape, it should be a precise inverse of `unlist`. These equalities hold:

       relist(unlist(x), x) == x
       unlist(relist(y, skeleton)) == y

       x <- as.relistable(x)
       relist(unlist(x)) == x

### Value

an object of (S3) class `"relistable"` (and `"list"`).

### Author(s)

R Core, based on a code proposal by Andrew Clausen.

### See Also

`unlist`

### Examples

     ipar <- list(mean = c(0, 1), vcov = cbind(c(1, 1), c(1, 0)))
     initial.param <- as.relistable(ipar)
     ul <- unlist(initial.param)
     relist(ul)
     stopifnot(identical(relist(ul), initial.param))

[Package utils version 4.0.5 Index]