Создайте новый столбец на основе условия из другого столбца для каждой группы, используя аккуратную оценку

Подобно этому вопросу, но я хочу использовать аккуратный оценка вместо этого.

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

Задача состоит в том, чтобы создать новый столбец (newValue), значения которого равны значениям столбца date (для каждой группы) с одним условием: speed == 4. Пример: group 1 имеет newValue из 2, потому что 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

Работало без аккуратной оценки

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 <- 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

Заранее спасибо.


person Reese Withouterspoon    schedule 11.05.2019    source источник


Ответы (2)


Мы можем заключить оценку в скобки. В противном случае он может попытаться оценить все выражение (filter_var[speed = 4L]), а не только filter_var.

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

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
person akrun    schedule 11.05.2019

Также можно использовать от sqldf. Присоединяйтесь к df с ограничением на это:

library(sqldf)
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))

sqldf("SELECT df_origin.*, df4.`date` new_value FROM 
       df df_origin join (SELECT `group`, `date` FROM df WHERE speed = 4) df4 
                    on (df_origin.`group` = df4.`group`)") 
person OmG    schedule 11.05.2019