1

After much searching, I can't seem to figure this out. Trying to write a function that:

  • takes a data frame, db
  • groups the data frame by var1
  • returns the mean and sd by group on several different columns

Here is my function,

myfun <- function(db,var1, ...) {

  var1 <- enquo(var1)
  var2 <- quos(...)

  for (i in var2) {

  db %>% 
    group_by(!!var1) %>%       
    summarise(mean_var = mean(!!!var2))

}}

when I pass the following, nothing returns

myfun(data, group, age, bmi)

Ideally, I would like to group both age and bmi by group and return the mean and sd for each. In the future, I would like to pass many more columns from data into the function...

The output would be similar to summaryBy from doby package, but on many columns at once and would look like:

Group   age.mean    age.sd
0
1
        bmi.mean    bmi.sd
0
1

1 Answer 1

2

Your loop appears to be unnecessary (you aren't doing anything with i). Instead, you could use summarize_at to achieve the effect you want:

myfun <- function(db,var1, ...) {

  var1 <- enquo(var1)
  var2 <- quos(...)

    db %>% 
      group_by(!!var1) %>%       
      summarise_at(vars(!!!var2), c(mean = mean, sd = sd))

  }

And if we test it out with diamonds dataset:

myfun(diamonds, cut, x, z)

  cut       x_mean z_mean  x_sd  z_sd
  <ord>      <dbl>  <dbl> <dbl> <dbl>
1 Fair        6.25   3.98 0.964 0.652
2 Good        5.84   3.64 1.06  0.655
3 Very Good   5.74   3.56 1.10  0.730
4 Premium     5.97   3.65 1.19  0.731
5 Ideal       5.51   3.40 1.06  0.658

To get the formatting closer to what you had in mind in your original post, we can use a bit of tidyr magic:

myfun <- function(db,var1, ...) {

  var1 <- enquo(var1)
  var2 <- quos(...)

  db %>% 
    group_by(!!var1) %>%       
    summarise_at(vars(!!!var2), c(mean = mean, sd = sd)) %>% 
    gather(variable, value, -(!!var1)) %>% 
    separate(variable, c('variable', 'measure'), sep = '_') %>% 
    spread(measure, value) %>% 
    arrange(variable, !!var1)

}

   cut       variable  mean    sd
   <ord>     <chr>    <dbl> <dbl>
 1 Fair      x         6.25 0.964
 2 Good      x         5.84 1.06 
 3 Very Good x         5.74 1.10 
 4 Premium   x         5.97 1.19 
 5 Ideal     x         5.51 1.06 
 6 Fair      z         3.98 0.652
 7 Good      z         3.64 0.655
 8 Very Good z         3.56 0.730
 9 Premium   z         3.65 0.731
10 Ideal     z         3.40 0.658
Sign up to request clarification or add additional context in comments.

2 Comments

This solution worked well for me. Can you explain how I might output the mean and sd by group for each column into a format which is similar to the original post? (more vertically aligned?, perhaps each result is outputted as a matrix?). If I input many more columns (x, y, z, a, b, c, etc...) the result is going to very difficult to read horizontally
This is precisely what I was looking for and works very well. I learned a lot from this answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.