【问题标题】:Summarize with custom function while calling values from outside of group从组外调用值时使用自定义函数进行汇总
【发布时间】:2020-07-27 20:41:06
【问题描述】:

我正在尝试使用 summarize_at() 和自定义函数来汇总多个列。我坚持的部分是函数ssmd() 旨在从group_by() 建立的组中获取一个值向量,并从该组之外获取另一个值向量。

在下面的示例中,x 应该是Month 的每组值的向量(根据当前组而变化),y 应该是Month == 5 的一组固定值。

# custom function
ssmd <- function(x, y){
  (mean(x, na.rm = TRUE) - mean(y, na.rm = TRUE)) / sqrt(var(x, na.rm = TRUE) + var(y, na.rm = TRUE))
}

# dataset
d <- airquality

# this isn't working - trying to find the difference between the mean for each Month and the mean of Month 5, for columns Ozone, Solar.R, Wind, and Temp
d %>%
  group_by(Month) %>%
  summarize_at(vars(Ozone:Temp), funs(ssmd, x = ., y = .[Month == 5])) %>%
  ungroup()

目前,这会产生以下错误:Error in mean(y, na.rm = TRUE) : argument "y" is missing, with no default。所以我认为我有一个语法错误,除了被困在如何从当前组之外访问值之外。

预期输出是一个数据框,每个月有一行,每个变量(Ozone、Solar.R、Wind 和 Temp)一列。

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    有两个问题:

    1) 当您在 funs 中引用 Month 时,它仅适用于该组,而不是整个数据框

    2) 1) 可以使用.$Month 解决,但您无权访问summarize_at 中的整个列来仅对Month == 5 中的值进行子集化。

    但是,您不需要该自定义函数,您可以为每个 Month 获取所有列的 mean,然后从 Month = 5 所在的每一列中减去值。

    library(dplyr)
    
    d %>%
      group_by(Month) %>%
      summarize_at(vars(Ozone:Temp), mean, na.rm = TRUE) %>%
      mutate_at(vars(Ozone:Temp), ~.  - .[Month == 5])
    
    # A tibble: 5 x 5
    #  Month Ozone Solar.R  Wind  Temp
    #  <int> <dbl>   <dbl> <dbl> <dbl>
    #1     5  0       0     0      0  
    #2     6  5.83    8.87 -1.36  13.6
    #3     7 35.5    35.2  -2.68  18.4
    #4     8 36.3    -9.44 -2.83  18.4
    #5     9  7.83  -13.9  -1.44  11.4
    

    要在更新后的帖子中使用ssmd 函数,我们可以这样做:

    library(dplyr)
    library(purrr)
    
    named_info <- d %>% select(Ozone:Temp) %>% names()
    
    map(named_info, function(x) d %>% group_by(Month) %>% 
                         summarise_at(vars(x), ~ssmd(., d[[x]][d$Month == 5]))) %>%
        reduce(inner_join, by = 'Month')
    

    【讨论】:

    • 你能举个例子,你如何正常使用phenoDist::ssmd函数,以及如何将它用于你的用例吗?
    • 对不起,我认为引入 phenoDist 不必要地使事情复杂化......我制作了一个自定义函数,以更好地反映我的用例。如果您再看一看,我将不胜感激。
    • @holastello 不,正如我在原始答案中已经展示的那样,总是有更好/不同的方法来做事。但是,我已经更新了答案以按照您的方式进行操作。希望对您有所帮助。
    【解决方案2】:

    我不知道如何修复您的语法错误,但我在这里提出了一种解决方法。这将数据汇总为每列的月平均值,然后减去第一个值,即五月的平均值。

    library(dplyr)
    
    d <- airquality
    
    d1 <- d %>%
      group_by(Month) %>%
      summarize_at(vars(Ozone:Temp), list(~mean(., na.rm = TRUE))) %>%
      ungroup()
    
    d1[-1] <- lapply(d1[-1], function(x) x - x[1])
    
    d1
    # # A tibble: 5 x 5
    #   Month Ozone Solar.R  Wind  Temp
    #   <int> <dbl>   <dbl> <dbl> <dbl>
    # 1     5  0       0     0      0  
    # 2     6  5.83    8.87 -1.36  13.6
    # 3     7 35.5    35.2  -2.68  18.4
    # 4     8 36.3    -9.44 -2.83  18.4
    # 5     9  7.83  -13.9  -1.44  11.4
    

    【讨论】:

    • @holastello 请提出一个新问题并提供可重现的示例,以表示真实的数据和功能。
    • 抱歉,我试图制作一个可重复性最低的示例,但我想我将其剥离得太远了。我编辑了函数以使其更好地反映我的用例。
    猜你喜欢
    • 1970-01-01
    • 2014-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    相关资源
    最近更新 更多