What is the difference between with and within in R? What is the difference between with and within in R? r r

What is the difference between with and within in R?


I find simple examples often work to highlight the difference. Something like:

df <- data.frame(a=1:5,b=2:6)df  a b1 1 22 2 33 3 44 4 55 5 6with(df, {c <- a + b; df;} )  a b1 1 22 2 33 3 44 4 55 5 6within(df, {c <- a + b; df;} )# equivalent to: within(df, c <- a + b)# i've just made the return of df explicit # for comparison's sake  a b  c1 1 2  32 2 3  53 3 4  74 4 5  95 5 6 11


The documentation is quite clear about the semantics and return values (and nicely matches the everyday meanings of the words “with” and “within”):

Value:

For ‘with’, the value of the evaluated ‘expr’. For ‘within’, the modified object.

Since your code doesn’t modify anything inside baseball, the unmodified baseball is returned. with on the other hand doesn’t return the object, it returns expr.

Here’s an example where the expression modifies the object:

> head(within(cars, speed[dist < 20] <- 1))
  speed dist1     1    22     1   103     1    44     7   225     1   166     1   10


As above, with returns the value of the last evaluated expression. It is handy for one-liners such as:

with(cars, summary(lm (speed ~ dist)))

but is not suitable for sending multiple expressions.

I often find within useful for manipulating a data.frame or list (or data.table) as I find the syntax easy to read.

I feel that the documentation could be improved by adding examples of use in this regard, e.g.:

df1 <- data.frame(a=1:3,              b=4:6,              c=letters[1:3])## library("data.table")  ## df1 <- as.data.table(df1)df1 <- within(df1, {    a <- 10:12    b[1:2] <- letters[25:26]    c <- a})df1

giving

    a b  c1: 10 y 102: 11 z 113: 12 6 12

and

df1 <- as.list(df1)df1 <- within(df1, {    a <- 20:23    b[1:2] <- letters[25:26]    c <- paste0(a, b)})df1

giving

$a[1] 20 21 22 23$b[1] "y" "z" "6"$c[1] "20y" "21z" "226" "23y"

Note also that methods("within") gives only these object types, being:

  • within.data.frame
  • within.list
  • (and within.data.table if the package is loaded).

Other packages may define additional methods.

Perhaps unexpectedly for some, with and within are generally not appropriate choices when manipulating variables within defined environments...

To address the comment - there is no within.environment method. Using with requires you to have the function you're calling within the environment, which somewhat defeats the purpose for me e.g.

df1 <- as.environment(df1)## with(df1, ls()) ## Errorassign("ls", ls, envir=df1)with(df1, ls())