【问题标题】:Use mutate with starts_with on columns and if_else在列和 if_else 上使用 mutate 和 starts_with
【发布时间】:2020-11-27 16:04:45
【问题描述】:

我有多个 Tibbles,我想成为 用一个函数改变它们。 问题是列名部分不同: 这就是我要申请的

mpg %>% mutate(model_QQ = if_else(year == 1999, 0 , if_else(cty > 20, 1, -1)))

但小标题的名称如下:

c("audi","nissan","subaru") %>% set_names() %>% map(~mpg %>% rename_at(vars(model:class), list(~str_c(.,"_",!!quo(.x)))))

我正在考虑制作类似的东西:

mpg %>% mutate(model_QQ = if_else(starts_with("year") == 1999, 0 , if_else(starts_with("cty") > 20, 1, -1)))

但这些仅在 select 函数内有效。 有什么建议吗?

编辑 我用 case when 重新编写代码,也许这样可以更清楚地说明我在寻找什么:

mpg %>% 
mutate(
model_QQ = case_when(

starts_with("year") == 1999 ~ 0L,
  starts_with("cty") > 20 ~ 1L,
  starts_with("cty") <= 20 ~ -1L
))

【问题讨论】:

    标签: r tidyverse tidy


    【解决方案1】:

    你可以这样做:

    mpg %>% 
      mutate(across(starts_with("year"), ~if_else(.x >= 1999, 0 , 1)), 
             across(starts_with("cty"),  ~if_else(.x > 20, 1, -1)))
    #> # A tibble: 234 x 11
    #>    manufacturer model  displ  year   cyl trans  drv     cty   hwy fl    class
    #>    <chr>        <chr>  <dbl> <dbl> <int> <chr>  <chr> <dbl> <int> <chr> <chr>
    #>  1 audi         a4       1.8     0     4 auto(~ f        -1    29 p     comp~
    #>  2 audi         a4       1.8     0     4 manua~ f         1    29 p     comp~
    #>  3 audi         a4       2       0     4 manua~ f        -1    31 p     comp~
    #>  4 audi         a4       2       0     4 auto(~ f         1    30 p     comp~
    #>  5 audi         a4       2.8     0     6 auto(~ f        -1    26 p     comp~
    #>  6 audi         a4       2.8     0     6 manua~ f        -1    26 p     comp~
    #>  7 audi         a4       3.1     0     6 auto(~ f        -1    27 p     comp~
    #>  8 audi         a4 qu~   1.8     0     4 manua~ 4        -1    26 p     comp~
    #>  9 audi         a4 qu~   1.8     0     4 auto(~ 4        -1    25 p     comp~
    #> 10 audi         a4 qu~   2       0     4 manua~ 4        -1    28 p     comp~
    #> # ... with 224 more rows
    
    

    或者,如果您希望将它们重命名为 year_modelQQcty_modelQQ,您可以这样做:

    mpg %>% 
      mutate(across(starts_with("year"), list(modelQQ = ~if_else(.x >= 1999, 0 ,1))), 
             across(starts_with("cty"),  list(modelQQ = ~if_else(.x > 20, 1, -1))))
    #> # A tibble: 234 x 13
    #>    manufacturer model displ  year   cyl trans drv     cty   hwy fl    class year_modelQQ
    #>    <chr>        <chr> <dbl> <int> <int> <chr> <chr> <int> <int> <chr> <chr>        <dbl>
    #>  1 audi         a4      1.8  1999     4 auto~ f        18    29 p     comp~            0
    #>  2 audi         a4      1.8  1999     4 manu~ f        21    29 p     comp~            0
    #>  3 audi         a4      2    2008     4 manu~ f        20    31 p     comp~            0
    #>  4 audi         a4      2    2008     4 auto~ f        21    30 p     comp~            0
    #>  5 audi         a4      2.8  1999     6 auto~ f        16    26 p     comp~            0
    #>  6 audi         a4      2.8  1999     6 manu~ f        18    26 p     comp~            0
    #>  7 audi         a4      3.1  2008     6 auto~ f        18    27 p     comp~            0
    #>  8 audi         a4 q~   1.8  1999     4 manu~ 4        18    26 p     comp~            0
    #>  9 audi         a4 q~   1.8  1999     4 auto~ 4        16    25 p     comp~            0
    #> 10 audi         a4 q~   2    2008     4 manu~ 4        20    28 p     comp~            0
    #> # ... with 224 more rows, and 1 more variable: cty_modelQQ <dbl>
    

    编辑

    有了更新的信息,这应该可以解决问题:

    mpg %>% 
      mutate(across(starts_with("year"), list(A = ~1 - (.x ==  1999))),
             across(starts_with("cty"), list(A = ~ -1 + 2*(.x > 20))),
             modelQQ = ifelse(year_A == 0, 0, cty_A)) %>%
      select(-ends_with("_A")
    

    【讨论】:

    • 这会改变这些列。我想新建一个名为model_QQ
    • @KGeles 但您在两个不同的列中有两个逻辑条件。对于以“year”开头的每一列和以“city”开头的每一列,您是否需要model_QQ?查看我的更新
    • 也许我不够清楚。我想为每个小标题添加一个名为“model_QQ”的列,该列将首先针对一个条件获得 0(发生在以“year”开头的列中),然后针对另一个条件获得 1 或 -1(列以“cty”开头)
    • @KGeles 我认为你的解释现在更清楚了。请查看我的更新。
    • @KGeles 如果您键入 ?across 并仔细阅读 .fns 参数的描述,它会告诉您如何将函数传递给 across 的不同选项,包括列表。这就是我使用的来源(当然还有 Stack Overflow!)
    【解决方案2】:

    我们可以使用case_when

    library(dplyr)
    mpg %>% 
       mutate(across(starts_with("year"), ~case_when(.x == 1999 ~ 0, TRUE ~ 1)), 
         across(starts_with("cty"),  ~case_when(.x > 20 ~ 1,  TRUE ~ -1)))
    

    如果是创建单列

    mpg %>% 
       mutate(model_QQ = case_when(select(., starts_with("year")) == 
         1999 ~ 0L, 
          select(., starts_with('cty')) > 20 ~ 1L, TRUE ~ -1L))
    

    -输出

    # A tibble: 234 x 12
    #   manufacturer model      displ  year   cyl trans      drv     cty   hwy fl    class   model_QQ
    #   <chr>        <chr>      <dbl> <int> <int> <chr>      <chr> <int> <int> <chr> <chr>      <int>
    # 1 audi         a4           1.8  1999     4 auto(l5)   f        18    29 p     compact        0
    # 2 audi         a4           1.8  1999     4 manual(m5) f        21    29 p     compact        0
    # 3 audi         a4           2    2008     4 manual(m6) f        20    31 p     compact       -1
    # 4 audi         a4           2    2008     4 auto(av)   f        21    30 p     compact        1
    # 5 audi         a4           2.8  1999     6 auto(l5)   f        16    26 p     compact        0
    # 6 audi         a4           2.8  1999     6 manual(m5) f        18    26 p     compact        0
    # 7 audi         a4           3.1  2008     6 auto(av)   f        18    27 p     compact       -1
    # 8 audi         a4 quattro   1.8  1999     4 manual(m5) 4        18    26 p     compact        0
    # 9 audi         a4 quattro   1.8  1999     4 auto(l5)   4        16    25 p     compact        0
    #10 audi         a4 quattro   2    2008     4 manual(m6) 4        20    28 p     compact       -1
    # … with 224 more rows
    

    【讨论】:

    • 对不起,我打错了,我也编辑了,应该是 starts_with("year") ==1999
    • 我改变了它并更好地阐明了预期的输出
    • 不幸的是,这不是我想要的。我添加了一个案例,我认为这会让事情变得更清楚
    • 感谢您的案例,非常优雅的制作方式!
    • 这很重要,因为它更容易理解!
    猜你喜欢
    • 2021-08-30
    • 2020-06-20
    • 2017-03-03
    • 1970-01-01
    • 1970-01-01
    • 2021-08-30
    • 2023-03-05
    • 2018-01-03
    • 2018-02-16
    相关资源
    最近更新 更多