【问题标题】:Perform a different simple custom function based on group根据组执行不同的简单自定义功能
【发布时间】:2021-01-29 23:44:25
【问题描述】:

我有包含三个组的数据,并希望对三个组中的每一个执行一个不同的自定义函数。与其编写三个单独的函数并分别调用它们,我想知道是否可以使用“组”参数轻松地将所有三个函数包装成一个函数。

例如,假设我想要 A 组的平均值:

library(tidyverse)

data(iris)

iris$Group <- c(rep("A", 50), rep("B", 50), rep("C", 50))

f_a <- function(df){
  out <- df %>% 
    group_by(Species) %>% 
    summarise(mean = mean(Sepal.Length))
  return(out)
}

B 组的中位数

f_b <- function(df){
  out <- df %>% 
    group_by(Species) %>% 
    summarise(median = median(Sepal.Length))
  return(out)
}

以及C组的标准差

f_c <- function(df){
  out <- df %>% 
    group_by(Species) %>% 
    summarise(sd= sd(Sepal.Length))
  return(out)
}

有没有什么办法可以把上面的函数组合起来,按照组参数运行??像: fx(df, group = "A") 哪个会产生上述 f_a 函数的结果??

请记住,在我的实际使用环境中,我不能简单地在原始函数中使用 group_by(group),因为实际函数更复杂。谢谢!!

【问题讨论】:

    标签: r function tidyverse


    【解决方案1】:

    我们在函数内部创建一个switch,以根据来自group 的匹配输入来选择要应用的适当函数。这个函数被传入summarise 以在'Species' groupihg 之后应用

    fx <- function(df, group) {
               fn_selector <- switch(group,
                            A = "mean",
                            B = "median",
                           C = "sd")
              
                           
                           
                 
              df %>%
                 group_by(Species) %>%
                 summarise(!! fn_selector :=
                 match.fun(fn_selector)(Sepal.Length), .groups = 'drop')
            }
    

    -测试

    fx(iris, "A")
    # A tibble: 3 x 2
    #  Species     mean
    #  <fct>      <dbl>
    #1 setosa      5.01
    #2 versicolor  5.94
    #3 virginica   6.59
     
    fx(iris, "B")
    # A tibble: 3 x 2
    #  Species    median
    #  <fct>       <dbl>
    #1 setosa        5  
    #2 versicolor    5.9
    #3 virginica     6.5
    
    fx(iris, "C")
    # A tibble: 3 x 2
    #  Species       sd
    #  <fct>      <dbl>
    #1 setosa     0.352
    #2 versicolor 0.516
    #3 virginica  0.636
    

    【讨论】:

    • 这本身很有帮助,但不完全是我想要的。我真的很想为每个组做完全不同的功能。像上面三个函数(f_a, f_b, f_c)一样,能不能合并成一个更大的函数??可能使用 if else??
    • @Lachlan 抱歉,您需要switch 函数还是基于已创建的“组”列应用三个函数?
    • @Lachlan 您能否检查一下更新是否是您要查找的内容。我在想你想在 group_by 中传递参数。对不起,这是我的错。
    • 这是我需要在我的问题中澄清的部分。我没有直接问,因为我认为一个更简单的例子可以解决它(那里可能是错误的)。我输入这个函数的每个 df 只有一组。所以我想执行三个功能之一,具体取决于 df 包含的组(A、B 或 C)。我现在将澄清我的问题
    • 是的,谢谢你介绍我切换——这正是我要找的功能!
    【解决方案2】:

    我不明白在数据集中有 group 列的意义。当我们在函数中传递group = "A" 时,这与创建的group 列无关。

    您可以直接传递要应用的函数,而不是在函数中传递group = "A",然后将A 映射到某个函数。

    library(dplyr)
    
    f_a <- function(df, fn){
      out <- df %>% 
              group_by(Species) %>% 
              summarise(out = fn(Sepal.Length))
      return(out)
    }
    
    f_a(iris, mean)
    
    # A tibble: 3 x 2
    #  Species      out
    #* <fct>      <dbl>
    #1 setosa      5.01
    #2 versicolor  5.94
    #3 virginica   6.59
    
    f_a(iris, median)
    # A tibble: 3 x 2
    #  Species      out
    #* <fct>      <dbl>
    #1 setosa       5  
    #2 versicolor   5.9
    #3 virginica    6.5
    

    【讨论】:

    • 我认为我过于简单化了我的问题并使其过于模糊。在我的真实数据中,每个不同的数据集都有一个包含 A、B 或 C 的列。根据该值,我想使用不同的函数。所以我读入数据帧,然后如果数据是 A 组,则应用函数 A,如果数据是 B 组,则应用函数 B 等等。我是编写函数的新手,所以做这样复杂的事情有点超出我的能力
    猜你喜欢
    • 1970-01-01
    • 2013-05-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-06
    • 2017-09-01
    • 2015-08-07
    • 2014-06-24
    • 1970-01-01
    相关资源
    最近更新 更多