【问题标题】:How to use enquo with a vector element in r如何在 r 中将 enquo 与向量元素一起使用
【发布时间】:2021-04-02 14:38:29
【问题描述】:

处理自定义函数时出现错误。“错误:Quosures 只能在 quasiquotation 上下文中不被引用。”很多类似的问答,但我在技术上还不足以解释。我所能辨别的是,这是我通过自定义函数调用 time_sec[event=='A'] 的尝试。违规行在下面的代码中注明。

library(dplyr)

# the data
set.seed(123)
event_df <- tibble(time_sec = c(1:120)) %>% 
  sample_n(100) %>%
  mutate(period = sample(c(1,2,3),
                         size = 100,
                         replace = TRUE),
         event = sample(c("A","B"), 
                        size = 100, 
                        replace = TRUE, 
                        prob = c(0.1,0.9))) %>% 
  select(period, time_sec, event) %>% 
  arrange(period, time_sec)

# the function
filter_within_timeframe <- function(.data, condition, time, lead_time = 0, lag_time = 0){
  condition <- enquo(condition)
  time <- enquo(time)
  filtered_lead <- c()
  filtered_lag <- c()
  
  if(lead_time > 0){
  # filter lead events
  filtered_lead <- .data %>%
    slice(., 1:max(which(!!condition))) %>%
    group_by(., grp =  lag(cumsum(!!condition), default = 0)) %>%
    filter(.,(last(!!time) - !!time) <= lead_time & (last(!!time) - !!time) >= 0) %>% 
    select(-grp)
  }

  if(lag_time > 0){
  #filter lag events
  filtered_lag <- .data %>%
    slice(min(which(!!condition)):nrow(.)) %>% # remove rows before first occurance
    group_by(grp =  lead(rev(cumsum(rev(!!condition))), default = 0), period) %>%
    filter((!!time - first(!!time[!!condition])) <= lag_time) # something in here doesn't work !!!!!!!!!!!!!
  }

  filtered <- rbind(filtered_lead, filtered_lag)
  return(filtered)
  
}

利用lead_time 的调用按预期工作......

event_df %>% filter_within_timeframe(event == 'A', time_sec, 10, 0)

...但是对 lag_time 的调用会引发错误..

event_df %>% filter_within_timeframe(event == 'A', time_sec, 0, 10)

【问题讨论】:

    标签: r


    【解决方案1】:

    您可以使用{{ }} 在函数中使用不带引号的列名。

    library(dplyr)
    
    filter_within_timeframe <- function(.data, condition, time, lead_time = 0, lag_time = 0){
      condition <- enquo(condition)
      filtered_lead <- c()
      filtered_lag <- c()
      
      if(lead_time > 0){
        # filter lead events
        filtered_lead <- .data %>%
          slice(., 1:max(which(!!condition))) %>%
          group_by(., grp =  lag(cumsum(!!condition), default = 0)) %>%
          filter(.,(last({{time}}) - {{time}}) <= lead_time & (last({{time}}) - {{time}}) >= 0) 
      }
      
      if(lag_time > 0){
        #filter lag events
        filtered_lag <- .data %>%
          slice(min(which(!!condition)):nrow(.)) %>% # remove rows before first occurance
          group_by(grp =  lead(rev(cumsum(rev(!!condition))), default = 0), period) %>%
          filter(({{time}} - first({{time}}[match(!!condition, TRUE)])) <= lag_time)
      }
      
      filtered <- rbind(filtered_lead, filtered_lag)
      return(filtered)
      
    }
    

    使用原始函数将变量替换为{{}} 后出现错误。我用match解决了。

    我们可以这样称呼它:

    event_df %>% filter_within_timeframe(event == 'A', time_sec, 10, 0)
    #     grp period time_sec event
    #   <dbl>  <dbl>    <int> <chr>
    # 1     0      1       43 B    
    # 2     0      1       45 B    
    # 3     0      1       52 A    
    # 4     1      1       54 A    
    # 5     2      1       61 B    
    # 6     2      1       64 B    
    # 7     2      1       70 A    
    # 8     3      1       92 B    
    # 9     3      1       95 A    
    #10     4      2       75 B    
    # … with 13 more rows
    
    event_df %>% filter_within_timeframe(event == 'A', time_sec, 0, 10)
    
    #  period time_sec event   grp
    #    <dbl>    <int> <chr> <dbl>
    # 1      1       52 A         7
    # 2      1       54 A         6
    # 3      1       58 B         6
    # 4      1       59 B         6
    # 5      1       61 B         6
    # 6      1       64 B         6
    # 7      1       70 A         5
    # 8      1       72 B         5
    # 9      1       74 B         5
    #10      1       76 B         5
    # … with 17 more rows
    

    【讨论】:

    • 作为 OP 的补充阅读 {{ }}(卷曲)是 rlang 0.4.0 的一个新的整洁 eval 运算符。额外的好处是您不再需要使用 enquo 来阻止对表达式的评估。
    猜你喜欢
    • 1970-01-01
    • 2021-01-29
    • 1970-01-01
    • 2015-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多