inst/doc/lazyeval.R

## ---- include = FALSE----------------------------------------------------
library(lazyeval)
knitr::opts_chunk$set(collapse = TRUE, comment = "#>")

## ---- fig.width = 4, fig.height = 2.5------------------------------------
par(mar = c(4.5, 4.5, 1, 0.5))
grid <- seq(0, 2 * pi, length = 100)
plot(grid, sin(grid), type = "l")

## ------------------------------------------------------------------------
df <- data.frame(x = c(1, 5, 4, 2, 3), y = c(2, 1, 5, 4, 3))

with(df, mean(x))
subset(df, x == y)
transform(df, z = x + y)

## ------------------------------------------------------------------------
my_label <- function(x) deparse(substitute(x))
my_label(x + y)

## ------------------------------------------------------------------------
my_label({
  a + b
  c + d
})

## ------------------------------------------------------------------------
my_label2 <- function(x) my_label(x)
my_label2(a + b)

## ------------------------------------------------------------------------
my_label <- function(x) expr_text(x)
my_label2 <- function(x) my_label(x)
   
my_label({
  a + b
  c + d
})
my_label2(a + b)

## ------------------------------------------------------------------------
expr_label(x)
expr_label(a + b + c)
expr_label(foo({
  x + y
}))

## ---- eval = FALSE-------------------------------------------------------
#  x <- c("a", "b", "c")
#  my_mean(x)
#  #> Error: `x` is a not a numeric vector.
#  my_mean(x == "a")
#  #> Error: `x == "a"` is not a numeric vector.
#  my_mean("a")
#  #> Error: "a" is not a numeric vector.

## ------------------------------------------------------------------------
f <- ~ x + y + z
typeof(f)
attributes(f)

## ------------------------------------------------------------------------
length(f)
# The 1st element is always ~
f[[1]]
# The 2nd element is the RHS
f[[2]]

## ------------------------------------------------------------------------
g <- y ~ x + z
length(g)
# The 1st element is still ~
g[[1]]
# But now the 2nd element is the LHS
g[[2]]
# And the 3rd element is the RHS
g[[3]]

## ------------------------------------------------------------------------
f_rhs(f)
f_lhs(f)
f_env(f)

f_rhs(g)
f_lhs(g)
f_env(g)

## ------------------------------------------------------------------------
f <- ~ 1 + 2 + 3
f
f_eval(f)

## ------------------------------------------------------------------------
x <- 1
add_1000 <- function(x) {
  ~ 1000 + x
}

add_1000(3)
f_eval(add_1000(3))

## ------------------------------------------------------------------------
f_unwrap(add_1000(3))

## ------------------------------------------------------------------------
y <- 100
f_eval(~ y)
f_eval(~ y, data = list(y = 10))

# Can mix variables in environment and data argument
f_eval(~ x + y, data = list(x = 10))
# Can even supply functions
f_eval(~ f(y), data = list(f = function(x) x * 3))

## ------------------------------------------------------------------------
f_eval(~ mean(cyl), data = mtcars)

## ---- eval = FALSE-------------------------------------------------------
#  f_eval(~ x, data = mydata)

## ------------------------------------------------------------------------
mydata <- data.frame(x = 100, y = 1)
x <- 10

f_eval(~ .env$x, data = mydata)
f_eval(~ .data$x, data = mydata)

## ---- error = TRUE-------------------------------------------------------
f_eval(~ .env$z, data = mydata)
f_eval(~ .data$z, data = mydata)

## ------------------------------------------------------------------------
df_mean <- function(df, variable) {
  f_eval(~ mean(uq(variable)), data = df)
}

df_mean(mtcars, ~ cyl)
df_mean(mtcars, ~ disp * 0.01638)
df_mean(mtcars, ~ sqrt(mpg))

## ------------------------------------------------------------------------
variable <- ~cyl
f_interp(~ mean(uq(variable)))

variable <- ~ disp * 0.01638
f_interp(~ mean(uq(variable)))

## ------------------------------------------------------------------------
f <- ~ mean
f_interp(~ uq(f)(uq(variable)))

## ------------------------------------------------------------------------
formula <- y ~ x
f_interp(~ lm(uq(formula), data = df))

## ------------------------------------------------------------------------
f_interp(~ lm(uqf(formula), data = df))

## ------------------------------------------------------------------------
variable <- ~ x
extra_args <- list(na.rm = TRUE, trim = 0.9)
f_interp(~ mean(uq(variable), uqs(extra_args)))

## ------------------------------------------------------------------------
f <- function(x) x + 1
f_eval(~ f(10), list(f = "a"))

## ------------------------------------------------------------------------
sieve <- function(df, condition) {
  rows <- f_eval(condition, df)
  if (!is.logical(rows)) {
    stop("`condition` must be logical.", call. = FALSE)
  }
  
  rows[is.na(rows)] <- FALSE
  df[rows, , drop = FALSE]
}

df <- data.frame(x = 1:5, y = 5:1)
sieve(df, ~ x <= 2)
sieve(df, ~ x == y)

## ---- eval = FALSE-------------------------------------------------------
#  sieve(march, ~ x > 100)
#  sieve(april, ~ x > 50)
#  sieve(june, ~ x > 45)
#  sieve(july, ~ x > 17)

## ------------------------------------------------------------------------
threshold_x <- function(df, threshold) {
  sieve(df, ~ x > threshold)
}
threshold_x(df, 3)

## ---- error = TRUE-------------------------------------------------------
rm(x)
df2 <- data.frame(y = 5:1)

# Throws an error
threshold_x(df2, 3)

# Silently gives the incorrect result!
x <- 5
threshold_x(df2, 3)

## ------------------------------------------------------------------------
df3 <- data.frame(x = 1:5, y = 5:1, threshold = 4)
threshold_x(df3, 3)

## ---- error = TRUE-------------------------------------------------------
threshold_x <- function(df, threshold) {
  sieve(df, ~ .data$x > .env$threshold)
}

threshold_x(df2, 3)
threshold_x(df3, 3)

## ------------------------------------------------------------------------
threshold <- function(df, variable, threshold) {
  stopifnot(is.character(variable), length(variable) == 1)
  
  sieve(df, ~ .data[[.env$variable]] > .env$threshold)
}
threshold(df, "x", 4)

## ------------------------------------------------------------------------
threshold <- function(df, variable = ~x, threshold = 0) {
  sieve(df, ~ uq(variable) > .env$threshold)
}

threshold(df, ~ x, 4)
threshold(df, ~ abs(x - y), 2)

## ------------------------------------------------------------------------
x <- 3
threshold(df, ~ .data$x - .env$x, 0)

## ------------------------------------------------------------------------
mogrify <- function(`_df`, ...) {
  args <- list(...)
  
  for (nm in names(args)) {
    `_df`[[nm]] <- f_eval(args[[nm]], `_df`)
  }
  
  `_df`
}

## ------------------------------------------------------------------------
df <- data.frame(x = 1:5, y = sample(5))
mogrify(df, z = ~ x + y, z2 = ~ z * 2)

## ------------------------------------------------------------------------
add_variable <- function(df, name, expr) {
  do.call("mogrify", c(list(df), setNames(list(expr), name)))
}
add_variable(df, "z", ~ x + y)

## ------------------------------------------------------------------------
f_list("x" ~ y, z = ~z)

## ------------------------------------------------------------------------
mogrify <- function(`_df`, ...) {
  args <- f_list(...)
  
  for (nm in names(args)) {
    `_df`[[nm]] <- f_eval(args[[nm]], `_df`)
  }
  
  `_df`
}

## ------------------------------------------------------------------------
add_variable <- function(df, name, expr) {
  mogrify(df, name ~ uq(expr))
}
add_variable(df, "z", ~ x + y)

## ------------------------------------------------------------------------
sieve_ <- function(df, condition) {
  rows <- f_eval(condition, df)
  if (!is.logical(rows)) {
    stop("`condition` must be logical.", call. = FALSE)
  }
  
  rows[is.na(rows)] <- FALSE
  df[rows, , drop = FALSE]
}

## ------------------------------------------------------------------------
sieve <- function(df, expr) {
  sieve_(df, f_capture(expr))
}
sieve(df, x == 1)

## ------------------------------------------------------------------------
scramble <- function(df) {
  df[sample(nrow(df)), , drop = FALSE]
}
subscramble <- function(df, expr) {
  scramble(sieve(df, expr))
}
subscramble(df, x < 4)

## ------------------------------------------------------------------------
mogrify_ <- function(`_df`, args) {
  args <- as_f_list(args)
  
  for (nm in names(args)) {
    `_df`[[nm]] <- f_eval(args[[nm]], `_df`)
  }
  
  `_df`
}

mogrify <- function(`_df`, ...) {
  mogrify_(`_df`, dots_capture(...))
}

Try the lazyeval package in your browser

Any scripts or data that you put into this service are public.

lazyeval documentation built on May 2, 2019, 2:11 a.m.