代码之家  ›  专栏  ›  技术社区  ›  Limey

过时的数据掩码。在“dplyr::mutate()结束后解析“xxxxxx”为时已晚`

  •  0
  • Limey  · 技术社区  · 3 年前

    this post ,我提出了一种完全通用的机制,通过这种机制,一个数据帧可以被另一个数据帧中存储的条件过滤。警察把我叫出来了(该死!)并要求我实施。

    功能 在筛选器数据帧中。这是可能的: this post 展示如何。

    library(tidyverse)
    
    longFilterTable <- tribble(
      ~var,   ~value,
      "gear", list(3),
    ) %>% 
      mutate(
        func=pmap(
          list(value),
          ~function(x) x == ..1[[1]]
        )
      )
    
    longFilterTable
    # A tibble: 1 x 3
      var   value      func  
      <chr> <list>     <list>
    1 gear  <list [1]> <fn>  
    

    这是一种非常复杂的说法“只选择那些行(共行)” mtcars )为了什么 gear 3 . 这样做有效:

    mtcars %>% filter(longFilterTable$func[[1]](gear)) %>% head(3)
                         mpg cyl  disp  hp drat    wt  qsec vs am gear carb
    Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
    Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
    Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
    Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
    <11 rows deleted for brevity>
    

    现在假设我想在标准上有更大的灵活性。例如,我可能希望选择一个值范围或一个固定值。这似乎是对上述过滤器数据集的合理扩展:

    longFilterTable <- tribble(
      ~var,   ~value,         ~condition,
      "gear", list(3),        "equal",
      "wt",   list(3,4, 3.9), "range",
    ) %>% 
      mutate(
        func=pmap(
          list(value, condition),
          ~function(x) {
            case_when(
              condition == "equal" ~ x == ..1[[1]],
              condition == "range" ~ x >= ..1[[1]][1] & x <= ..1[[1]][2],
              TRUE ~ x
            )
          }
        )
      )
    
    longFilterTable
    # A tibble: 2 x 4
      var   value      condition func  
      <chr> <list>     <chr>     <list>
    1 gear  <list [1]> equal     <fn>  
    2 wt    <list [3]> range     <fn>  
    

    但现在当我尝试应用过滤器时,我得到:

    mtcars %>% filter(longFilterTable$func[[1]](gear))
     Show Traceback
     
     Rerun with Debug
     Error: Problem with `filter()` input `..1`.
    x Obsolete data mask.
    x Too late to resolve `condition` after the end of `dplyr::mutate()`.
    ℹ Did you save an object that uses `condition` lazily in a column in the `dplyr::mutate()` expression ?
    ℹ Input `..1` is `longFilterTable$func[[1]](gear)`.
    

    我玩过各种各样的 deparse() substitute() expression() , force() eval() ,但无济于事。有人能找到解决办法吗?

    1 回复  |  直到 3 年前
        1
  •  0
  •   mnist    3 年前

    你的问题是所有的选择 case_when

    x <- 1
    
    dplyr::case_when(x < 2 ~ TRUE,
                     x < 0 ~ FALSE)
    #> [1] TRUE
    
    dplyr::case_when(x < 2 ~ TRUE,
                     x < 0 ~ stop())
    #> Error in eval_tidy(pair$rhs, env = default_env):
    

    value 列表,结果是 NA 只有s,因此是错误的。正在从切换 什么时候

    library(purrr)
    library(dplyr)
    longFilterTable <- tribble(
      ~var,   ~value,         ~condition,
      "gear", list(3),        "equal",
      "wt",   list(3.4, 3.9), "range",
    ) %>% 
      mutate(
        func=pmap(
          list(value, condition),
          ~function(x) {
            if(..2 == "equal") x == ..1[[1]]
            else if (..2 == "range") x >= ..1[[1]] & x <= ..1[[2]]
            else TRUE
          }
        )
      )
    
    
    mtcars %>% filter(longFilterTable$func[[2]](drat))
    #>                mpg cyl  disp  hp drat    wt  qsec vs am gear carb
    #> Mazda RX4     21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
    #> Mazda RX4 Wag 21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
    #> Datsun 710    22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
    #> Merc 240D     24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
    #> Toyota Corona 21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1