【问题标题】:c_across multiple functions per rows with dplyrc_across 使用 dplyr 每行的多个函数
【发布时间】:2021-07-23 17:31:14
【问题描述】:

是否可以使用rowwise()c_across() 在每行的同一 c_across 语句中应用多个函数。使用across() 函数,我们可以使用每个列的函数列表,它是否也适用于 c_across?

#sample data
df <- tibble(a = c(1, 2, 3, 25, 1),
             b = c(5, 26, 8, 8, 3),
             c = c(9, 10, 11, 11, 12),
             d = c('a', 'b', 'c', 'd', 'e'),
             e = c(1, 2, 3, 4, 7))


#This will work

df %>% 
  rowwise() %>% 
  mutate(max = max (c_across(where(is.numeric)), na.rm = TRUE) ,
         min = min (c_across(where(is.numeric)), na.rm = TRUE),
         avg = mean(c_across(where(is.numeric)), na.rm = TRUE))

# A tibble: 5 x 8
# Rowwise: 
      a     b     c d         e   max   min   avg
  <dbl> <dbl> <dbl> <chr> <dbl> <dbl> <dbl> <dbl>
1     1     5     9 a         1     9     1  4.33
2     2    26    10 b         2    26     2 11.3 
3     3     8    11 c         3    11     3  6.5 
4    25     8    11 d         4    25     4 12.8 
5     1     3    12 e         7    12     1  6  

#This returns errors
df %>% 
  rowwise() %>% 
  mutate(c_across(where(is.numeric)), 
  list( mean = ~mean(., na.rm = TRUE), min = ~min(., na.rm = TRUE),
      max = ~max(., na.rm = TRUE)))

【问题讨论】:

    标签: r dplyr tidyverse


    【解决方案1】:

    我认为您的“这将起作用”实际上不起作用。当您执行变异时,它会考虑您之前创建的列。即,在计算平均值时,它也会选择 minmax 列。第 1 行的列 a, b, c, e 的平均值应为 16/4 = 4,而不是 26/6 = 4.33。但我想我明白你在说什么......

    诚然,这感觉有点 hacky,但它确实有效(至少在示例数据上)。 across 能够获取函数列表,因为它返回 tibble。此解决方案的目的是让它从一系列 c_across 变异中返回一个 tibble。因为原始数据(df)是分开的,所以它至少为您提供了我个人期望的平均值

    df %>% 
      rowwise() %>% 
      mutate(
        across(1,
          list( mean = ~mean(c_across(where(is.numeric)), na.rm = TRUE),
                min = ~min(c_across(where(is.numeric)), na.rm = TRUE),
                max = ~max(c_across(where(is.numeric)), na.rm = TRUE)),
          .names = "{.fn}"
        )
      )
    #> # A tibble: 5 x 8
    #> # Rowwise: 
    #>       a     b     c d         e  mean   min   max
    #>   <dbl> <dbl> <dbl> <chr> <dbl> <dbl> <dbl> <dbl>
    #> 1     1     5     9 a         1  4        1     9
    #> 2     2    26    10 b         2 10        2    26
    #> 3     3     8    11 c         3  6.25     3    11
    #> 4    25     8    11 d         4 12        4    25
    #> 5     1     3    12 e         7  5.75     1    12
    

    reprex package (v1.0.0) 于 2021-04-30 创建

    由于提供的函数都忽略了实际选择的列(即使用c_across(where(is.numeric))来确定相关列而不是cross提供的列,所以您可以使用任何单个,有效的列作为第一个across 的参数。关键是只提供一列,以便函数只计算一次。我使用了第 1 列,因为通常可以安全地假设您的 data.frame 至少有一列。

    【讨论】:

    • 是的,你是对的,“这将起作用”实际上并没有起作用。我忽略了它,我必须先计算平均值以避免选择最小和最大列
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-06
    • 1970-01-01
    • 2014-03-16
    • 1970-01-01
    相关资源
    最近更新 更多