【问题标题】:rowwise() sum with vector of column names in dplyrrowwise() 与 dplyr 中的列名向量求和
【发布时间】:2021-09-27 07:12:17
【问题描述】:

我再次对如何实现这一点感到困惑:

给定这个数据框:

df <- tibble(
  foo = c(1,0,1),
  bar = c(1,1,1),
  foobar = c(0,1,1)
)

还有这个向量:

to_sum <- c("foo", "bar")

我想获得to_sum 列中值的逐行总和。

期望的输出:

# A tibble: 3 x 4
# Rowwise: 
    foo   bar foobar   sum
  <dbl> <dbl>  <dbl> <dbl>
1     1     1      0     2
2     0     1      1     1
3     1     1      1     2

打字有效(显然)。

df %>% rowwise() %>% 
  mutate(
    sum = sum(foo, bar)
  )

这不是:

df %>% rowwise() %>% 
  mutate(
    sum = sum(to_sum)
  )

我明白,因为如果我要尝试:

df %>% rowwise() %>% 
  mutate(
    sum = sum("foo", "bar")
  )

如何从列名向量计算逐行总和?

【问题讨论】:

    标签: r dplyr rlang


    【解决方案1】:

    您需要使用c_acrossany_of。这就是 RStudio 团队打算使用它的方式:查看vignette("rowwise", package = "dplyr")

    library(dplyr)
    
    df %>% 
      rowwise() %>% 
      mutate(sum = sum(c_across(any_of(to_sum))))
    
    #> # A tibble: 3 x 4
    #> # Rowwise: 
    #>     foo   bar foobar   sum
    #>   <dbl> <dbl>  <dbl> <dbl>
    #> 1     1     1      0     2
    #> 2     0     1      1     1
    #> 3     1     1      1     2
    

    c_across 特定于行操作。 需要any_ofto_sum 解释为包含列名的字符向量。即使没有它也可以工作,但通常首选使用它。

    您可能希望在末尾使用ungroup() 删除rowwise

    【讨论】:

      【解决方案2】:

      我认为您正在寻找 rlang::syms 将字符串强制转换为 quosures:

      library(dplyr)
      library(rlang)
      df %>% 
        rowwise() %>% 
        mutate(
          sum = sum(!!!syms(to_sum))
        )
      #     foo   bar foobar   sum
      #   <dbl> <dbl>  <dbl> <dbl>
      # 1     1     1      0     2
      # 2     0     1      1     1
      # 3     1     1      1     2
      

      【讨论】:

      • 简洁优雅。
      • 这就是我要找的。我用!!syms() 试过了,但忘了我应该把它“解开”三倍。
      【解决方案3】:

      这可能会对您有所帮助:

      library(dplyr)
      library(purrr)
      library(rlang)
      
      df %>%
        bind_cols(parse_exprs(to_sum) %>%
                    map_dfc(~ eval_tidy(.x, data = df)) %>%
                    rowSums()) %>%
        rename(sum = ...4)
      
      # A tibble: 3 x 4
          foo   bar foobar   sum
        <dbl> <dbl>  <dbl> <dbl>
      1     1     1      0     2
      2     0     1      1     1
      3     1     1      1     2
      

      【讨论】:

        【解决方案4】:
        library(janitor)
        df %>%
          adorn_totals("col",,,"sum",to_sum)
        
         foo bar foobar sum
           1   1      0   2
           0   1      1   1
           1   1      1   2
        

        为什么是,,,

        如果您查看?adorn_totals,您会看到它的论点:

        adorn_totals(dat, where = "row", fill = "-", na.rm = TRUE, name = "Total", ...)

        最后一个... 是控制列选择。不幸的是,没有办法直接告诉 R to_sum 应该用于 ... 参数,所以这个答案中的 ,,, 告诉它使用参数 wherefill, 和 @ 的默认值987654332@。此时,除了... 之外,它对每个参数都有值,因此to_sum 被应用于该参数。

        此处进一步讨论该主题:Specify the dots argument when calling a tidyselect-using function without needing to specify the preceding arguments

        【讨论】:

        • 不错!我不熟悉这种,,, 技术。你能解释一下吗?
        • 是的,我刚刚在解释它的答案中添加了更多内容。
        • 感谢您的解决方案。我不知道你的janitor 包。我一定会调查的。
        【解决方案5】:

        你也可以考虑使用rowSums:

        df %>% 
           mutate(sum = rowSums(across(all_of(to_sum))))
        
        # A tibble: 3 x 4
            foo   bar foobar   sum
          <dbl> <dbl>  <dbl> <dbl>
        1     1     1      0     2
        2     0     1      1     1
        3     1     1      1     2
        

        【讨论】:

        • 确实不错的解决方案。我接受了!!!syms() 解决方案,但我喜欢这不需要rowwise() 功能。谢谢
        猜你喜欢
        • 2018-03-05
        • 1970-01-01
        • 1970-01-01
        • 2016-01-10
        • 1970-01-01
        • 2019-09-19
        • 1970-01-01
        • 2021-04-01
        • 1970-01-01
        相关资源
        最近更新 更多