Create new column based on condition from other column per group using tidy evaluation [Solved]

Similar to this question but I want to use tidy evaluation instead.

df = data.frame(group = c(1,1,1,2,2,2,3,3,3), 
                date  = c(1,2,3,4,5,6,7,8,9),
                speed = c(3,4,3,4,5,6,6,4,9))
> df
  group date speed
1     1    1     3
2     1    2     4
3     1    3     3
4     2    4     4
5     2    5     5
6     2    6     6
7     3    7     6
8     3    8     4
9     3    9     9

The task is to create a new column (newValue) that equals to the values of the date column (per group) with one condition: speed == 4. Example: group 1 has a newValue of 2 because date[speed==4] = 2.

    group date speed newValue
1     1    1     3        2
2     1    2     4        2
3     1    3     3        2
4     2    4     4        4
5     2    5     5        4
6     2    6     6        4
7     3    7     6        8
8     3    8     4        8
9     3    9     9        8

If I do it as normal then everything is fine

df %>%
  group_by(group) %>%
  mutate(newValue=date[speed==4L])
#> # A tibble: 9 x 4
#> # Groups:   group [3]
#>   group  date speed newValue
#>   <dbl> <dbl> <dbl>    <dbl>
#> 1     1     1     3        2
#> 2     1     2     4        2
#> 3     1     3     3        2
#> 4     2     4     4        4
#> 5     2     5     5        4
#> 6     2     6     6        4
#> 7     3     7     6        8
#> 8     3     8     4        8
#> 9     3     9     9        8

Error with tidy evaluation

my_fu <- function(df, filter_var){
  filter_var <- sym(filter_var)
  df <- df %>%
	group_by(group) %>%
	mutate(newValue=!!filter_var[speed==4L])
}

my_fu(df, "date")
#> Error in quos(..., .named = TRUE): object 'speed' not found

Thanks in advance.

You have this error because !! applies here on the whole filter_var[speed==4L].

You need parenthesis to isolate the use of !! or need to consider [ as a function.
Also, inside function, it is recommended to use ensym or enquo. The last one will allow you to pass argument date instead of "date".

Here are examples

df = data.frame(group = c(1,1,1,2,2,2,3,3,3), 
                date  = c(1,2,3,4,5,6,7,8,9),
                speed = c(3,4,3,4,5,6,6,4,9))

library(dplyr)
#> 
#> Attachement du package : 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
df %>%
  group_by(group) %>%
  mutate(newValue=date[speed==4L])
#> # A tibble: 9 x 4
#> # Groups:   group [3]
#>   group  date speed newValue
#>   <dbl> <dbl> <dbl>    <dbl>
#> 1     1     1     3        2
#> 2     1     2     4        2
#> 3     1     3     3        2
#> 4     2     4     4        4
#> 5     2     5     5        4
#> 6     2     6     6        4
#> 7     3     7     6        8
#> 8     3     8     4        8
#> 9     3     9     9        8

my_fu <- function(df, filter_var){
  filter_var <- ensym(filter_var)
  df <- df %>%
    group_by(group) %>%
    # mutate(newValue=`[`(!!filter_var, speed == 4L))
    mutate(newValue=(!!filter_var)[speed == 4L])
  return(df)
}

my_fu(df, "date")
#> # A tibble: 9 x 4
#> # Groups:   group [3]
#>   group  date speed newValue
#>   <dbl> <dbl> <dbl>    <dbl>
#> 1     1     1     3        2
#> 2     1     2     4        2
#> 3     1     3     3        2
#> 4     2     4     4        4
#> 5     2     5     5        4
#> 6     2     6     6        4
#> 7     3     7     6        8
#> 8     3     8     4        8
#> 9     3     9     9        8

my_fu2 <- function(df, filter_var){
  filter_var <- enquo(filter_var)
  df <- df %>%
    group_by(group) %>%
    mutate(newValue=`[`(!!filter_var, speed == 4L))
  return(df)
}

my_fu2(df, date)
#> # A tibble: 9 x 4
#> # Groups:   group [3]
#>   group  date speed newValue
#>   <dbl> <dbl> <dbl>    <dbl>
#> 1     1     1     3        2
#> 2     1     2     4        2
#> 3     1     3     3        2
#> 4     2     4     4        4
#> 5     2     5     5        4
#> 6     2     6     6        4
#> 7     3     7     6        8
#> 8     3     8     4        8
#> 9     3     9     9        8

Created on 2019-05-11 by the reprex package (v0.2.1.9000)

3 Likes

Thanks @cderv!!!!!!!!!!!!!

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.