Susie Derkins
Susie Derkins

Reputation: 2638

Writing function that calculates rowwise mean for subset of columns and creates column name

I want to turn this line of code into a function:

mutate(var_avg = rowMeans(select(., starts_with("var"))))

It works in the pipe:

df <- read_csv("var_one,var_two,var_three
1,1,1
2,2,2
3,3,3")

df %>% mutate(var_avg = rowMeans(select(., starts_with("var"))))

># A tibble: 3 x 4
>  var_one var_two var_three var_avg
>    <dbl>   <dbl>     <dbl>   <dbl>
>1       1       1         1       1
>2       2       2         2       2
>3       3       3         3       3

Here's my attempt (I'm new at writing functions):

colnameMeans <- function(x) {
  columnname <- paste0("avg_",x)
  mutate(columnname <- rowMeans(select(., starts_with(x))))
}

It doesn't work.

df %>% colnameMeans("var")
>Error in colnameMeans(., "var") : unused argument ("var")

I have a lot to learn about functions and I'm not sure where to start with fixing this. Any help would be much appreciated. Note that this is a simplified example. In my real data, I have several column prefixes and I want to calculate a row-wise mean for each one. EDIT: Being able to run the function for multiple prefixes at once would be a bonus.

Upvotes: 1

Views: 46

Answers (1)

akrun
akrun

Reputation: 887901

If we need to assign column name on the lhs of assignment, use := and evaluate (!!) the string. The <- inside mutate won't work as the default option is = and it would evaluate unquoted value on the lhs of = literally. In addition, we may need to specify the data as argument in the function

library(dplyr)
colnameMeans <- function(., x) { 
   columnname<- paste0("avg_", x)
   mutate(., !! columnname := rowMeans(select(., starts_with(x))))
  }
df %>% 
  colnameMeans('var')
# A tibble: 3 x 4
#  var_one var_two var_three avg_var
#    <dbl>   <dbl>     <dbl>   <dbl>
#1       1       1         1       1
#2       2       2         2       2
#3       3       3         3       3

If there are several prefixes, use map

library(purrr)
library(stringr)
colnameMeans <- function(., x) { 
   columnname<- paste0("avg_", x)
   transmute(., !! columnname := rowMeans(select(., starts_with(x))))
  }


map_dfc(c('var', 'alt'), ~ df1 %>%
        colnameMeans(.x)) %>%
      bind_cols(df1, .)
# A tibble: 3 x 8
#  var_one var_two var_three alt_var_one alt_var_two alt_var_three avg_var avg_alt
#*   <dbl>   <dbl>     <dbl>       <dbl>       <dbl>         <dbl>   <dbl>   <dbl>
#1       1       1         1           1           1             1       1       1
#2       2       2         2           2           2             2       2       2
#3       3       3         3           3           3             3       3       3

data

df1 <- bind_cols(df,  df %>% rename_all(~ str_replace(., 'var_', 'new_')))

Upvotes: 1

Related Questions