tidyverse / funs

Collection of low-level functions for working with vctrs
Other
34 stars 7 forks source link

vec_expand() #30

Closed DavisVaughan closed 4 years ago

DavisVaughan commented 4 years ago

Potentially useful vec_expand() for inserting NA (or other) values. It is like vec_slice(x, c(1:2, NA_integer_, 3:4)) but the way you specify it is a bit easier

library(tibble)
library(vctrs)
library(rlang)

vec_expand <- function(x, i, fill = NULL) {
  vec_assert(x)

  i <- vec_cast(i, integer())
  i <- vec_unique(i)

  if (any(i <= 0L)) {
    abort("`i` must be positive.")
  }

  size_i <- vec_size(i)
  size_x <- vec_size(x)
  size_out <- size_x + size_i

  slicer <- vec_init(integer(), size_out)
  pos_x_in_out <- seq_len(size_out)[-i]
  vec_slice(slicer, pos_x_in_out) <- seq_len(size_x)

  out <- vec_slice(x, slicer)

  if (is.null(fill)) {
    return(out)
  }

  vec_slice(out, i) <- fill

  out
}

vec_expand(1:5, c(2, 5))
#> [1]  1 NA  2  3 NA  4  5

df <- tibble(
  x = 1:5,
  y = 6:10
)

vec_expand(df, 2)
#> # A tibble: 6 x 2
#>       x     y
#>   <int> <int>
#> 1     1     6
#> 2    NA    NA
#> 3     2     7
#> 4     3     8
#> 5     4     9
#> 6     5    10

vec_expand(df, -2)
#> `i` must be positive.

vec_expand(df, c(2, 2, 7, 4))
#> # A tibble: 8 x 2
#>       x     y
#>   <int> <int>
#> 1     1     6
#> 2    NA    NA
#> 3     2     7
#> 4    NA    NA
#> 5     3     8
#> 6     4     9
#> 7    NA    NA
#> 8     5    10

vec_expand(df, c(2, 7, 4), fill = data.frame(x = -1, y = -2))
#> # A tibble: 8 x 2
#>       x     y
#>   <int> <int>
#> 1     1     6
#> 2    -1    -2
#> 3     2     7
#> 4    -1    -2
#> 5     3     8
#> 6     4     9
#> 7    -1    -2
#> 8     5    10

vec_expand(df, c(2, 4), fill = data.frame(x = c(-1, -1), y = c(-2, -3)))
#> # A tibble: 7 x 2
#>       x     y
#>   <int> <int>
#> 1     1     6
#> 2    -1    -2
#> 3     2     7
#> 4    -1    -3
#> 5     3     8
#> 6     4     9
#> 7     5    10

Created on 2019-10-04 by the reprex package (v0.2.1)

hadley commented 4 years ago

Do you have examples of when you might use this? It feels a bit specialised to me.

DavisVaughan commented 4 years ago

Probably too specialized, can't remember why I thought it was useful