首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >R dplyr -在summarize_at链中使用'count‘函数

R dplyr -在summarize_at链中使用'count‘函数
EN

Stack Overflow用户
提问于 2020-11-07 00:01:03
回答 1查看 47关注 0票数 0

这是R中dplyr库中的数据帧starwars。我正在尝试使用dplyr编写聚合表,主要使用group_by_atsummarize_at链。我已经定义了向量dimensionsVecmeasuresVec和函数。目标是使用分配给数据帧pivotDatadplyr链中的所有三个向量。

不幸的是,在运行pivotData之后尝试输出数据帧时,count = length参数不起作用。这可能是由于na.rm = TRUE语句造成的。因此,基本上,除了函数中的count = length参数之外,一切都可以正常工作。您可以通过注释掉`函数向量的count = length部分来发现这一点。

有谁能帮我吗?非常感谢你的帮助!

下面的代码片段

代码语言:javascript
复制
library(dplyr)

data <- starwars

dimensionsVec <- c("skin_color", "eye_color")
measuresVec <- c("height", "mass")

functions <- c(count = "length", 
               mean = "mean", 
               sum = "sum", 
               median = "median", 
               max = "max", 
               min = "min")

funsList <- lapply(functions, match.fun)
names(funsList) <- functions

pivotData <- data %>%
  group_by_at(vars(dimensionsVec)) %>%
  summarize_at(vars(measuresVec), funsList, na.rm = TRUE) %>%
  collect()
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-11-07 00:23:43

你只需要小心你要传递的函数。除非可以将na.rm = TRUE参数传递给列表中的所有函数,否则不能将该参数添加到summarize_at。但是,如果您将na.rm = TRUE传递给length,它将抛出一个错误。

一种解决方法是在接受na.rm参数的length周围创建一个包装器:

代码语言:javascript
复制
funsList <- list(count = function(x, na.rm) length(x),
                 mean = mean,
                 sum = sum, 
                 median = median, 
                 max = max, 
                 min = min)

(请注意,您可以直接使用无引号的函数名,而不是将它们全部作为字符串并使用match.fun)

这种方法是可行的,但它揭示了代码中的另一个问题。您要汇总的一些组没有非NA条目,因此您实际上是在对某些组执行min(NA, na.rm = TRUE)。这会导致一个警告,并在结果中返回您可能不想要的Inf而不是NA。同样,你会从meanmedian得到一个带有maxNaN的不想要的-Inf

解决方案是具体说明您希望每个函数在此场景中执行的操作。例如,您可以创建一个小函数,该函数将汇总函数作为参数并返回它们的安娜安全版本:

代码语言:javascript
复制
handle_NA <- function(func) 
{
  function(x) if(all(is.na(x))) NA else func(x, na.rm = TRUE) 
}

这使您可以创建一个安全的funsList,如下所示:

代码语言:javascript
复制
funsList <- list(count = length,
                 mean = handle_NA(mean),
                 sum = handle_NA(sum),
                 median = handle_NA(median), 
                 max = handle_NA(max), 
                 min = handle_NA(min))

data %>%
  group_by(across(all_of(dimensionsVec))) %>%
  summarize(across(all_of(measuresVec), funsList), .groups = "drop")
#> # A tibble: 53 x 14
#>    skin_color eye_color height_count height_mean height_sum height_median
#>    <chr>      <chr>            <int>       <dbl>      <int>         <dbl>
#>  1 blue       blue                 1        196         196          196 
#>  2 blue       hazel                1        178         178          178 
#>  3 blue, grey yellow               2        116.        231          116.
#>  4 brown      blue                 1        234         234          234 
#>  5 brown      brown                2        130.        259          130.
#>  6 brown      yellow               1        198         198          198 
#>  7 brown mot~ orange               1        180         180          180 
#>  8 brown, wh~ green, y~            1        216         216          216 
#>  9 dark       blue                 1        184         184          184 
#> 10 dark       brown                4        183.        733          184 
#> # ... with 43 more rows, and 8 more variables: height_max <int>,
#> #   height_min <int>, mass_count <int>, mass_mean <dbl>, mass_sum <dbl>,
#> #   mass_median <dbl>, mass_max <dbl>, mass_min <dbl>

请注意,限定了作用域的动词summarize_atgroup_by_at已被使用across取代,因此我已切换到更现代的语法。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64717892

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档