3
df <- data.frame(a=factor(c(1,1,2,2,3,3) ), b=c(1,1, 10,10, 20,20) )

  a  b
1 1  1
2 1  1
3 2 10
4 2 10
5 3 20
6 3 20

I want to split the data frame by column a, calculate b/sum(b) in each group, and put the result in column c. With plyr I can do:

fun <- function(x){
  x$c=x$b/sum(x$b)
  x
} 
ddply(df, .(a), fun )

and have

  a  b   c
1 1  1 0.5
2 1  1 0.5
3 2 10 0.5
4 2 10 0.5
5 3 20 0.5
6 3 20 0.5

but how can I do it with dplyr?

df %.% group_by(a) %.% do(fun)

returns a list instead of a data.frame.

Flux
  • 815
  • 1
  • 6
  • 6
  • I believe that that is simply how `do` works at the moment (returning a list of each piece). I seem to recall that changing this so that `do` stitches them back together was in the works as a change in the near future. You might try the dev version from github. – joran Apr 23 '14 at 15:46
  • ...but for this particular example, I think all you need is `mutate`. – joran Apr 23 '14 at 15:47

2 Answers2

5
df %>%
  group_by(a) %>%
  mutate(c=b/sum(b))

  a  b   c
1 1  1 0.5
2 1  1 0.5
3 2 10 0.5
4 2 10 0.5
5 3 20 0.5
6 3 20 0.5
eipi10
  • 91,525
  • 24
  • 209
  • 285
  • Thanks. This is a simplified example and my original df is a tbl produced by summarise() and has another column as group. That column causes some problem when using mutate. Is there a way to force re-group by 'a' other than as.data.frame()? – Flux Apr 23 '14 at 16:01
  • Can you update your question with a specific reproducible example? That would make it easier to solve your problem. – eipi10 Apr 23 '14 at 16:09
  • Just guessing here, but does [this SO question](http://stackoverflow.com/questions/21653295/dplyr-issues-with-group-by?rq=1) address the issue you're having? – eipi10 Apr 23 '14 at 16:11
2

Just to mention an R base solution, you can use transform (R base equivalent to mutate) and ave function to split vectors and apply functions.

> transform(df, c=ave(b,a, FUN= function(b) b/sum(b)))
  a  b   c
1 1  1 0.5
2 1  1 0.5
3 2 10 0.5
4 2 10 0.5
5 3 20 0.5
6 3 20 0.5
Jilber Urbina
  • 58,147
  • 10
  • 114
  • 138