hatmatrix
hatmatrix

Reputation: 44892

dplyr do() without dot pronoun?

In dplyr::do(), is there a way to access variables in the context of .data as with other dplyr functions? For instance, say I have a data frame:

> dd <- data.frame(a=1:5)

mutate(), as well as other functions, works so that expressions are evaluated in the context of the data frame:

> mutate(dd,a2=a*2)
  a a2
1 1  2
2 2  4
3 3  6
4 4  8
5 5 10

But not do:

> do(dd,data.frame(a2=a[1:2]*2))
Error in eval(expr, envir, enclos) : object 'a' not found

I can accomplish my objective using with() and the dot pronoun:

> do(dd,with(.,data.frame(a2=a[1:2]*2)))
  a2
1  2
2  4

I am also not sure why this doesn't work:

> do(dd,function(X) data.frame(a2=X$a[1:2]*2))
Error: Result must be a data frame

Questions:

  1. Is there logic to why this behavior (scope) is different from mutate, select, etc.
  2. Is there an elegant solution or I have to keep using with() if I don't want to keep using .$variablename in the expression?
  3. Why doesn't the anonymous function work? Seems like it works here but not sure why my case is different.

Upvotes: 2

Views: 763

Answers (1)

James
James

Reputation: 66834

  1. mutate, select, etc are specialised functions designed to have the data argument first which work with piping of magrittr and help with non-standard evaluation. do is a more general function which can not make the same assumptions.

  2. It depends on what you are trying to do. If you use a function with non-standard evaluation, you will only need to provide the . once.

For example:

do(dd, transform(.,a2=a*2)[1:2,]["a2"])
  a2
1  2
2  4

But it is no better than with really. The best code golf would be:

do(dd, data.frame(a2=.$a[1:2]*2))
  a2
1  2
2  4

But it depends on how often you want to refer to the original data.frame. You may find it easier and more readable to use the specialsed functions with piping for this task.

  1. You need to call the anonymous function otherwise it is just returning the function definition.

Like so:

do(dd,{function(X) data.frame(a2=X$a[1:2]*2)}(.))
  a2
1  2
2  4

Upvotes: 3

Related Questions