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) slide_vec( .x, .f, ..., .before = 0L, .after = 0L, .step = 1L, .complete = FALSE, .ptype = NULL ) slide_dbl( .x, .f, ..., .before = 0L, .after = 0L, .step = 1L, .complete = FALSE ) slide_int( .x, .f, ..., .before = 0L, .after = 0L, .step = 1L, .complete = FALSE ) slide_lgl( .x, .f, ..., .before = 0L, .after = 0L, .step = 1L, .complete = FALSE ) slide_chr( .x, .f, ..., .before = 0L, .after = 0L, .step = 1L, .complete = FALSE ) slide_dfr( .x, .f, ..., .before = 0L, .after = 0L, .step = 1L, .complete = FALSE, .names_to = rlang::zap(), .name_repair = c("unique", "universal", "check_unique") ) slide_dfc( .x, .f, ..., .before = 0L, .after = 0L, .step = 1L, .complete = FALSE, .size = NULL, .name_repair = c("unique", "universal", "check_unique", "minimal") )
| .x |
The vector to iterate over and apply |
|---|---|
| .f |
If a function, it is used as is. If a formula, e.g.
This syntax allows you to create very compact anonymous functions. |
| ... | Additional arguments passed on to the mapped function. |
| .before, .after |
The number of values before or after the current element to
include in the sliding window. Set to |
| .step |
The number of elements to shift the window forward between function calls. |
| .complete |
Should |
| .ptype |
A prototype corresponding to the type of the output. If If supplied, the result of each call to If |
| .names_to | This controls what to do with input names supplied in
|
| .name_repair | One of With |
| .size | If, Alternatively, specify the desired number of rows, and any inputs of length 1 will be recycled appropriately. |
A vector fulfilling the following invariants:
slide()vec_size(slide(.x)) == vec_size(.x)
vec_ptype(slide(.x)) == list()
slide_vec() and slide_*() variantsvec_size(slide_vec(.x)) == vec_size(.x)
vec_size(slide_vec(.x)[[1]]) == 1L
vec_ptype(slide_vec(.x, .ptype = ptype)) == ptype
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.
# The defaults work similarly to `map()` slide(1:5, ~.x)#> [[1]] #> [1] 1 #> #> [[2]] #> [1] 2 #> #> [[3]] #> [1] 3 #> #> [[4]] #> [1] 4 #> #> [[5]] #> [1] 5 #># Use `.before`, `.after`, and `.step` to control the window slide(1:5, ~.x, .before = 1)#> [[1]] #> [1] 1 #> #> [[2]] #> [1] 1 2 #> #> [[3]] #> [1] 2 3 #> #> [[4]] #> [1] 3 4 #> #> [[5]] #> [1] 4 5 #>#> [1] -0.55369938 0.03764133 0.71343585 0.35433918 0.31548748#> [[1]] #> [1] 0 #> #> [[2]] #> [1] -0.6704995 0.6704995 #> #> [[3]] #> [1] -1.0504695 0.2905295 0.7599401 #> #> [[4]] #> [1] -0.51147315 -0.04206255 0.55353570 #> #> [[5]] #> [1] 0.08862489 0.68422314 -0.77284803 #># `.after` allows you to "align to the left" rather than the right slide(1:5, ~.x, .after = 2)#> [[1]] #> [1] 1 2 3 #> #> [[2]] #> [1] 2 3 4 #> #> [[3]] #> [1] 3 4 5 #> #> [[4]] #> [1] 4 5 #> #> [[5]] #> [1] 5 #># 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)#> [[1]] #> [1] 1 2 #> #> [[2]] #> [1] 1 2 3 #> #> [[3]] #> [1] 2 3 4 #> #> [[4]] #> [1] 3 4 5 #> #> [[5]] #> [1] 4 5 #># 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)#> [[1]] #> [1] 1 #> #> [[2]] #> NULL #> #> [[3]] #> NULL #> #> [[4]] #> [1] 2 3 4 #> #> [[5]] #> NULL #> #> [[6]] #> NULL #> #> [[7]] #> [1] 5 6 7 #> #> [[8]] #> NULL #> #> [[9]] #> NULL #> #> [[10]] #> [1] 8 9 10 #># `.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)#> [[1]] #> [1] 1 2 #> #> [[2]] #> [1] 1 2 3 #> #> [[3]] #> [1] 1 2 3 4 #> #> [[4]] #> [1] 2 3 4 5 #> #> [[5]] #> [1] 3 4 5 #>slide(1:5, ~.x, .before = 2, .after = 1, .complete = TRUE)#> [[1]] #> NULL #> #> [[2]] #> NULL #> #> [[3]] #> [1] 1 2 3 4 #> #> [[4]] #> [1] 2 3 4 5 #> #> [[5]] #> NULL #># --------------------------------------------------------------------------- # Data frames # Data frames are iterated over rowwise mtcars_rowwise <- slide(mtcars, ~.x) mtcars_rowwise[1:3]#> $`Mazda RX4` #> mpg cyl disp hp drat wt qsec vs am gear carb #> Mazda RX4 21 6 160 110 3.9 2.62 16.46 0 1 4 4 #> #> $`Mazda RX4 Wag` #> mpg cyl disp hp drat wt qsec vs am gear carb #> Mazda RX4 Wag 21 6 160 110 3.9 2.875 17.02 0 1 4 4 #> #> $`Datsun 710` #> mpg cyl disp hp drat wt qsec vs am gear carb #> Datsun 710 22.8 4 108 93 3.85 2.32 18.61 1 1 4 1 #># This means that any column name is easily accessible slide_dbl(mtcars, ~.x$mpg + .x$cyl)#> Mazda RX4 Mazda RX4 Wag Datsun 710 Hornet 4 Drive #> 27.0 27.0 26.8 27.4 #> Hornet Sportabout Valiant Duster 360 Merc 240D #> 26.7 24.1 22.3 28.4 #> Merc 230 Merc 280 Merc 280C Merc 450SE #> 26.8 25.2 23.8 24.4 #> Merc 450SL Merc 450SLC Cadillac Fleetwood Lincoln Continental #> 25.3 23.2 18.4 18.4 #> Chrysler Imperial Fiat 128 Honda Civic Toyota Corolla #> 22.7 36.4 34.4 37.9 #> Toyota Corona Dodge Challenger AMC Javelin Camaro Z28 #> 25.5 23.5 23.2 21.3 #> Pontiac Firebird Fiat X1-9 Porsche 914-2 Lotus Europa #> 27.2 31.3 30.0 34.4 #> Ford Pantera L Ferrari Dino Maserati Bora Volvo 142E #> 23.8 25.7 23.0 25.4# More advanced rowwise iteration is available as well by using the # other arguments mtcars_rowwise_window <- slide(mtcars, ~.x, .before = 1, .after = 1) mtcars_rowwise_window[1:3]#> $`Mazda RX4` #> mpg cyl disp hp drat wt qsec vs am gear carb #> Mazda RX4 21 6 160 110 3.9 2.620 16.46 0 1 4 4 #> Mazda RX4 Wag 21 6 160 110 3.9 2.875 17.02 0 1 4 4 #> #> $`Mazda RX4 Wag` #> mpg cyl disp hp drat wt qsec vs am gear carb #> Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4 #> Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 #> Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 #> #> $`Datsun 710` #> mpg cyl disp hp drat wt qsec vs am gear carb #> Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 #> Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 #> Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 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)#> [[1]] #> [1] 1 #> #> [[2]] #> [1] 1 2 #> #> [[3]] #> [1] 1 2 3 #> #> [[4]] #> [1] 1 2 3 4 #> #> [[5]] #> [1] 1 2 3 4 5 #># 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)#> [[1]] #> [1] 1 2 3 4 5 #> #> [[2]] #> [1] 2 3 4 5 #> #> [[3]] #> [1] 3 4 5 #> #> [[4]] #> [1] 4 5 #> #> [[5]] #> [1] 5 #># --------------------------------------------------------------------------- # 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)#> [[1]] #> [1] 2 3 #> #> [[2]] #> [1] 3 4 #> #> [[3]] #> [1] 4 5 #> #> [[4]] #> [1] 5 #> #> [[5]] #> integer(0) #># `.after` can be negative as well to "look backwards" slide(1:5, ~.x, .before = 2, .after = -1)#> [[1]] #> integer(0) #> #> [[2]] #> [1] 1 #> #> [[3]] #> [1] 1 2 #> #> [[4]] #> [1] 2 3 #> #> [[5]] #> [1] 3 4 #># --------------------------------------------------------------------------- # 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)#> [1] NA NA NA 0.06608461 NA 0.30607315 #> [7] NA 0.20981554 NA -0.82274657# 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( i, ~data.frame(start = .x[1], stop = .x[length(.x)]), .before = 3, .step = 2, .complete = TRUE ) idx#> start stop #> 1 1 4 #> 2 3 6 #> 3 5 8 #> 4 7 10#> [1] 0.06608461 0.30607315 0.20981554 -0.82274657