## Writing ts-functions

It is straightforward to turn existing functions into functions that can deal with any ts-boxable object.

The `ts_`

function is a constructor function for tsbox
time series functions. It can be used to wrap any function that works
with time series. The default is set to R base `"ts"`

class,
so wrapping functions for `"ts"`

time series (or vectors or
matrices) is as simple as:

Note that `ts_`

returns a function, which can be with or
without a name. Let’ have a closer look at how `ts_rowsums`

looks like:

```
ts_rowsums
#> function (x, ...)
#> {
#> stopifnot(ts_boxable(x))
#> z <- rowSums(ts_ts(x), ...)
#> copy_class(z, x)
#> }
```

This is how most ts-functions work. They use a specific converter
function (here: `ts_ts`

) to convert a ts-boxable object to
the desired class. They then perform the main operation on the object
(here: `rowSums`

). Finally they convert the result back to
the original class, using `copy_class`

.

The resulting function has a `...`

argument. You can use
it to pass arguments to the underlying functions. E.g.,

`ts_rowsums(ts_c(mdeaths, fdeaths), na.rm = TRUE)`

## Functions from external packages

Here is a slightly more complex example, which uses a post processing function:

It is easy to make functions from external packages ts-boxable, by
wrapping them into `ts_`

.

```
ts_dygraphs <- ts_(dygraphs::dygraph, class = "xts")
ts_forecast <- ts_(function(x, ...) forecast::forecast(x, ...)$mean, vectorize = TRUE)
ts_seas <- ts_(function(x, ...) seasonal::final(seasonal::seas(x, ...)), vectorize = TRUE)
ts_dygraphs(ts_c(mdeaths, EuStockMarkets))
ts_forecast(ts_c(mdeaths, fdeaths))
ts_seas(ts_c(mdeaths, fdeaths))
```

If you are explicit about the namespace (e.g.,
`dygraphs::dygraph`

), `ts_`

recognized the package
in use and delivers a meaningful message if the package is not
installed.

Note that the `ts_`

function deals with the conversion
stuff, ‘vectorizes’ the function so that it can be used with multiple
time series.

Let’ have another look at `ts_forecast`

:

```
ts_forecast
#> function (x, ...)
#> {
#> load_suggested("forecast")
#> ff <- function(x, ...) {
#> stopifnot(ts_boxable(x))
#> z <- (function(x, ...) forecast::forecast(ts_na_omit(x),
#> ...)$mean)(ts_ts(x), ...)
#> copy_class(z, x)
#> }
#> ts_apply(x, ff, ...)
#> }
```

There three differences to the `ts_rowsum`

example: First,
the function requires the forecast package. If it is not installed,
`load_suggested`

will ask the user to do so. Second, the
function in use is an anonymous function,
`function(x) forecast::forecast(x, ...)$mean`

, that also
extracts the `$mean`

component from the result. Third, the
function is ‘vectorized’, using `ts_apply`

. This causes the
process to be repeated for each time series in the object.