slide: Slide

View source: R/slide.R

slideR Documentation



slide() iterates through .x using a sliding window, applying .f to each sub-window of .x.


slide(.x, .f, ..., .before = 0L, .after = 0L, .step = 1L, .complete = FALSE)

  .before = 0L,
  .after = 0L,
  .step = 1L,
  .complete = FALSE,
  .ptype = NULL

  .before = 0L,
  .after = 0L,
  .step = 1L,
  .complete = FALSE

  .before = 0L,
  .after = 0L,
  .step = 1L,
  .complete = FALSE

  .before = 0L,
  .after = 0L,
  .step = 1L,
  .complete = FALSE

  .before = 0L,
  .after = 0L,
  .step = 1L,
  .complete = FALSE

  .before = 0L,
  .after = 0L,
  .step = 1L,
  .complete = FALSE,
  .names_to = rlang::zap(),
  .name_repair = c("unique", "universal", "check_unique")

  .before = 0L,
  .after = 0L,
  .step = 1L,
  .complete = FALSE,
  .size = NULL,
  .name_repair = c("unique", "universal", "check_unique", "minimal")




The vector to iterate over and apply .f to.


⁠[function / formula]⁠

If a function, it is used as is.

If a formula, e.g. ~ .x + 2, it is converted to a function. There are three ways to refer to the arguments:

  • For a single argument function, use .

  • For a two argument function, use .x and .y

  • For more arguments, use ..1, ..2, ..3 etc

This syntax allows you to create very compact anonymous functions.


Additional arguments passed on to the mapped function.

.before, .after

⁠[integer(1) / Inf]⁠

The number of values before or after the current element to include in the sliding window. Set to Inf to select all elements before or after the current element. Negative values are allowed, which allows you to "look forward" from the current element if used as the .before value, or "look backwards" if used as .after.


⁠[positive integer(1)]⁠

The number of elements to shift the window forward between function calls.



Should the function be evaluated on complete windows only? If FALSE, the default, then partial computations will be allowed.


⁠[vector(0) / NULL]⁠

A prototype corresponding to the type of the output.

If NULL, the default, the output type is determined by computing the common type across the results of the calls to .f.

If supplied, the result of each call to .f will be cast to that type, and the final output will have that type.

If getOption("vctrs.no_guessing") is TRUE, the .ptype must be supplied. This is a way to make production code demand fixed types.


This controls what to do with input names supplied in ....

  • By default, input names are zapped.

  • If a string, specifies a column where the input names will be copied. These names are often useful to identify rows with their original input. If a column name is supplied and ... is not named, an integer column is used instead.

  • If NULL, the input names are used as row names.


One of "unique", "universal", "check_unique", "unique_quiet", or "universal_quiet". See vec_as_names() for the meaning of these options.

With vec_rbind(), the repair function is applied to all inputs separately. This is because vec_rbind() needs to align their columns before binding the rows, and thus needs all inputs to have unique names. On the other hand, vec_cbind() applies the repair function after all inputs have been concatenated together in a final data frame. Hence vec_cbind() allows the more permissive minimal names repair.


If, NULL, the default, will determine the number of rows in vec_cbind() output by using the tidyverse recycling rules.

Alternatively, specify the desired number of rows, and any inputs of length 1 will be recycled appropriately.


Unlike lapply() or purrr::map(), which construct calls like

.f(.x[[i]], ...)

the equivalent with slide() looks like

.f(vctrs::vec_slice(.x, i), ...)

which is approximately

.f(.x[i], ...)

except in the case of data frames or arrays, which are iterated over row-wise.

If .x has names, then the output will preserve those names.

Using vctrs::vec_cast(), the output of .f will be automatically cast to the type required by the variant of ⁠slide_*()⁠ being used.


A vector fulfilling the following invariants:


  • vec_size(slide(.x)) == vec_size(.x)

  • vec_ptype(slide(.x)) == list()

slide_vec() and ⁠slide_*()⁠ variants

  • vec_size(slide_vec(.x)) == vec_size(.x)

  • vec_size(slide_vec(.x)[[1]]) == 1L

  • vec_ptype(slide_vec(.x, .ptype = ptype)) == ptype

See Also

slide2(), slide_index(), hop()


# The defaults work similarly to `map()`
slide(1:5, ~.x)

# Use `.before`, `.after`, and `.step` to control the window
slide(1:5, ~.x, .before = 1)

# This can be used for rolling means
slide_dbl(rnorm(5), mean, .before = 2)

# Or more flexible rolling operations
slide(rnorm(5), ~ .x - mean(.x), .before = 2)

# `.after` allows you to "align to the left" rather than the right
slide(1:5, ~.x, .after = 2)

# And a mixture of `.before` and `.after`
# allows you complete control over the exact alignment.
# Below, "center alignment" is used.
slide(1:5, ~.x, .before = 1, .after = 1)

# The `.step` controls how the window is shifted along `.x`,
# allowing you to "skip" iterations if you only need a less granular result
slide(1:10, ~.x, .before = 2, .step = 3)

# `.complete` controls whether or not partial results are computed.
# By default, they are, but setting `.complete = TRUE` restricts
# `slide()` to only evaluate the function where a complete window exists.
slide(1:5, ~.x, .before = 2, .after = 1)
slide(1:5, ~.x, .before = 2, .after = 1, .complete = TRUE)

# ---------------------------------------------------------------------------
# Data frames

# Data frames are iterated over rowwise
mtcars_rowwise <- slide(mtcars, ~.x)

# This means that any column name is easily accessible
slide_dbl(mtcars, ~.x$mpg + .x$cyl)

# More advanced rowwise iteration is available as well by using the
# other arguments
mtcars_rowwise_window <- slide(mtcars, ~.x, .before = 1, .after = 1)

# ---------------------------------------------------------------------------
# Cumulative sliding

# Using the special cased value, `Inf`, you can ask `slide()` to pin the
# start of the sliding window to the first element, effectively creating
# a cumulative window
slide(1:5, ~.x, .before = Inf)

# Same with `.after`, this creates a window where you start with all of the
# elements, but decrease the total number over each iteration
slide(1:5, ~.x, .after = Inf)

# ---------------------------------------------------------------------------
# Negative `.before` / `.after`

# `.before` is allowed to be negative, allowing you to "look forward" in
# your vector. Note that `abs(.before) <= .after` must hold if `.before` is
# negative. In this example, we look forward to elements in locations 2 and 3
# but place the result in position 1 in the output.
slide(1:5, ~.x, .before = -1, .after = 2)

# `.after` can be negative as well to "look backwards"
slide(1:5, ~.x, .before = 2, .after = -1)

# ---------------------------------------------------------------------------
# Removing padding

# If you are looking for a way to remove the `NA` values from something like
# this, then it doesn't exist as a built in option.
x <- rnorm(10)
slide_dbl(x, mean, .before = 3, .step = 2, .complete = TRUE)

# Adding an option to `slide_dbl()` to remove the `NA` values would destroy
# its size stability. Instead, you can use a combination of `slide_dfr()`
# to get the start/stop indices with `hop_index_vec()`.
i <- seq_along(x)
idx <- slide_dfr(
  ~data.frame(start = .x[1], stop = .x[length(.x)]),
  .before = 3,
  .step = 2,
  .complete = TRUE


hop_index_vec(x, i, idx$start, idx$stop, mean, .ptype = double())

slider documentation built on Oct. 12, 2023, 5:11 p.m.