1
#' Fill with data.table
2
#'
3
#' Fills in values, similar to \code{tidyr::fill()}, by within \code{data.table}. This function relies on the
4
#' \code{Rcpp} functions that drive \code{tidyr::fill()} but applies them within \code{data.table}.
5
#'
6
#' @param dt_ the data table (or if not a data.table then it is coerced with as.data.table)
7
#' @param ... the columns to fill
8
#' @param id the grouping variable(s) to fill within
9
#' @param .direction either "down" or "up" (down fills values down, up fills values up), or "downup" (down first then up) or "updown" (up first then down)
10
#'
11
#' @examples
12
#'
13
#' set.seed(84322)
14
#' library(data.table)
15
#'
16
#' x = 1:10
17
#' dt = data.table(v1 = x,
18
#'                 v2 = shift(x),
19
#'                 v3 = shift(x, -1L),
20
#'                 v4 = sample(c(rep(NA, 10), x), 10),
21
#'                 grp = sample(1:3, 10, replace = TRUE))
22
#' dt_fill(dt, v2, v3, v4, id = grp, .direction = "downup")
23
#' dt_fill(dt, v2, v3, v4, id = grp)
24
#' dt_fill(dt, .direction = "up")
25
#'
26
#' @importFrom data.table as.data.table
27
#'
28
#' @export
29
dt_fill <- function(dt_, ..., id = NULL, .direction = c("down", "up", "downup", "updown")){
30 1
  UseMethod("dt_fill", dt_)
31
}
32

33
#' @export
34
dt_fill.default <- function(dt_, ..., id = NULL, .direction = c("down", "up", "downup", "updown")){
35

36 1
  if (isFALSE(is.data.table(dt_)))
37 0
    dt_ <- data.table::as.data.table(dt_)
38

39 1
  .direction <- match.arg(.direction)
40 1
  fun <- switch(.direction,
41 1
                "down"   = fillDown,
42 1
                "up"     = fillUp,
43 1
                "downup" = function(x) fillUp(fillDown(x)),
44 1
                "updown" = function(x) fillDown(fillUp(x)))
45

46 1
  dots  <- paste_dots(...)
47 1
  by    <- substitute(id)
48

49 1
  dt_[, lapply(.SD, fun), by = eval(by), .SDcols = dots]
50
}
51

52
paste_dots <- function(...){
53 1
  paste(substitute(c(...)))[-1]
54
}

Read our documentation on viewing source code .

Loading