---
title: "B. Advanced usage"
author: "Gerold Hepp"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{B. Advanced usage}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
```

This vignette illustrates some more advanced concepts of the `DTSg` package, namely reference semantics, chaining and piping as well as swallowing and dropping.

---

First, let's load the package as well as some data and let's create a `DTSg` object:

```{r}
library(DTSg)

data(flow)
TS <- DTSg$new(flow)
TS
```

## Reference semantics

By default, every method manipulating the values of a `DTSg` object creates a deep clone (copy) of it beforehand. This behaviour can be overridden by setting the `clone` argument of the respective method to `FALSE`. Globally, deep cloning can be controlled with the help of the *DTSgClone* option:

```{r}
TS$alter("2007-01-01", "2008-12-31")
# `TS` was deep cloned before shortening it, hence its end date is still in the
# year 2012
TS

options(DTSgClone = FALSE)
getOption("DTSgClone")
# `TS` was modified in place this time, hence its end date is in the year 2008
# now
TS$alter("2007-01-01", "2008-12-31")
TS
```

As we can see, with cloning set to `FALSE`, the object was altered in place, i.e. no assignment to a new or reassignment to an existing variable was necessary in order to make the changes stick. This is due to the R6 nature of `DTSg` objects.

### Note

Using reference semantics can result in undesired behaviour. Merely assigning a variable representing a `DTSg` object to a new variable does not result in a copy of the object. Instead, both variables will reference and access the same data under the hood, i.e. changing one will also affect the other. In case you want a "real" copy of a `DTSg` object, you will have to use the `clone()` method with its `deep` argument set to `TRUE` (for consistency with the `R6` package its default is `FALSE`):

```{r}
TSc <- TS$clone(deep = TRUE)
# or 'clone(TS, deep = TRUE)'
```

## Chaining and piping

Especially in combination with reference semantics, chaining and piping can be a fast and comfortable way to apply several object manipulations in a row. While chaining only works in combination with the R6 interface, piping is an exclusive feature of the S3 interface.

Let's start with chaining:

```{r}
TS <- DTSg$
  new(flow)$
  alter("2007-01-01", "2008-12-31")$
  colapply(interpolateLinear)$
  aggregate(byYm____, mean)
TS
```

For piping, we have to make sure that R 4.1.0 or later is installed in order to have access to R's native pipe operator `|>` (alternatively, the same can be achieved with the forward-pipe operator `%>%` of the `magrittr` package):

```{r}
TS <- new("DTSg", flow) |>
  alter("2007-01-01", "2008-12-31") |>
  colapply(interpolateLinear) |>
  aggregate(byYm____, mean)
TS
```

## Swallowing and dropping

An extension to reference semantics of existing `DTSg` objects are reference semantics during object creation. This behaviour can be triggered with the help of the `swallow` argument of the `new()` method. When set to `TRUE`, a `data.table` provided through the `values` argument is "swallowed" by the `DTSg` object, i.e. no copy of it is made and all references to it are removed from the global (and only the global) environment upon successful object creation:

```{r}
library(data.table)

DT <- copy(flow)
ls(pattern = "^DT$")
TS <- DTSg$new(DT, swallow = TRUE)
ls(pattern = "^DT$")
```

The opposite of swallowing is called dropping. This term refers to querying the values of a `DTSg` object as a reference while removing all references to the original `DTSg` object from the global (and again only the global) environment at the same time:

```{r}
TS <- DTSg$new(flow)
ls(pattern = "^TS$")
DT <- TS$values(drop = TRUE)
ls(pattern = "^TS$")
```

## Column access

Sometimes need may arise to access a column other than the one currently processed from a function within the `colapply()` method. This can be accomplished in the following way:

```{r}
# add a new column recording if a certain value is missing or not before
# carrying out a linear interpolation
TS <- DTSg$new(flow)
TS$summary()
TS$
  colapply(
    function(x, ...) is.na(x),
    resultCols = "missing"
  )$
  colapply(interpolateLinear)$
  summary()

# undo the linear interpolation (requires additional access to the previously
# created column named "missing", which can be carried out with the help of the
# `getCol` method or its shortcut, the `[` operator, and the freely chosen `y`
# argument)
TS$
  colapply(
    function(x, y, ...) ifelse(y, NA, x),
    y = TS$getCol("missing") # or 'y = TS["missing"]'
  )$
  summary()
```

Please refer to the help pages for further details.