Apply a list to a function that outputs a datafram

2019-05-22 21:44发布

问题:

My single-argument function outputs a dataframe

library(tidyverse) 
myfun <-function(x) {mtcars %>%
                         filter_(x) %>%
                         group_by(cyl) %>%
                         summarise(mean(disp), mean(drat)) %>%
                         mutate(group=x)}

When feeding a single-argument into this function, it outputs, as expected, a dataframe:

   myfun('mpg>15')

   cyl      mean(disp)   mean(drat)     group
    4       105           4.07          mpg>15
    6       183           3.59          mpg>15
    8       105           3.20          mpg>15

How to apply such a function to a list of arguments so that the output is one dataframe combining all the results over the list. For example, I'd like to apply myfun to a list

c('mpg>15', 'drat>4.2')

and, as the result, to obtain a single dataframe:

cyl      mean(disp)   mean(drat)     group
 4       105           4.07          mpg>15
 6       183           3.59          mpg>15
 8       105           3.20          mpg>15
 4       89            4.53          drat>4.2
 8       351           4.22          drat>4.2

How to do that (preferably within tidyverse)?

回答1:

To stay in tidyverse, maybe something like this:

c("mpg>15", "am==1") %>% map(myfun) %>% bind_rows

But, as @alistaire points out in a comment, you can shorten this by using map_df, which returns a data frame:

c("mpg>15", "am==1") %>% map_df(myfun)

A mixed option, three equivalent ways, using lapply:

lapply(c("mpg>15", "am==1"), myfun) %>% bind_rows 
c("mpg>15", "am==1") %>% lapply(myfun) %>% bind_rows
bind_rows(lapply(c("mpg>15", "am==1"), myfun))

Or, to get a little more perverse about mixing base and tidyverse:

c("mpg>15", "am==1") %>% lapply(myfun) %>% do.call(rbind, .)

And for base R traditionalists:

do.call(rbind, lapply(c("mpg>15", "am==1"), myfun))