如何在R中用map对列表内tibble指定分组行的n值求和
需求与问题描述
我有大量存储在列表中的计数表数据,部分行需要按指定标签聚合。简化示例数据如下:
# 构造示例数据 df <- list( x1 = tibble::tibble( fruits = c("apple", "orange", "banana", "pineapple"), n = sample(1:10, 4) ), x2 = tibble::tibble( fruits = c("apple", "orange", "banana", "pineapple"), n = sample(1:10, 4) ) )
输出结果:
#> $x1 #> # A tibble: 4 × 2 #> fruits n #> <chr> <int> #> 1 apple 4 #> 2 orange 3 #> 3 banana 2 #> 4 pineapple 1 #> #> $x2 #> # A tibble: 4 × 2 #> fruits n #> <chr> <int> #> 1 apple 8 #> 2 orange 5 #> 3 banana 7 #> 4 pineapple 6
需要将包含"apple"的行标记为"--",处理后的数据集df2如下:
df2 <- df |> purrr::map(\(x) { x |> dplyr::mutate(across(1, \(i) { ifelse(stringr::str_detect(i, "apple"), "--", i) })) })
输出结果:
#> $x1 #> # A tibble: 4 × 2 #> fruits n #> <chr> <int> #> 1 -- 4 #> 2 orange 3 #> 3 banana 2 #> 4 -- 1 #> #> $x2 #> # A tibble: 4 × 2 #> fruits n #> <chr> <int> #> 1 -- 8 #> 2 orange 5 #> 3 banana 7 #> 4 -- 6
现在需要对fruits列为"--"的行的n值求和,尝试用map结合summarise实现,但得到错误结果:
df2 |> purrr::map(\(x) { x |> dplyr::summarise(across(2, \(i) { n = sum(n) .by = fruits })) })
输出结果(含警告):
#> Warning: Returning more (or less) than 1 row per `summarise()` group was deprecated in #> dplyr 1.1.0. #> ℹ Please use `reframe()` instead. #> ℹ When switching from `summarise()` to `reframe()`, remember that `reframe()` #> always returns an ungrouped data frame and adjust accordingly. #> Warning: Returning more (or less) than 1 row per `summarise()` group was deprecated in #> dplyr 1.1.0. #> ℹ Please use `reframe()` instead. #> ℹ When switching from `summarise()` to `reframe()`, remember that `reframe()` #> always returns an ungrouped data frame and adjust accordingly. #> $x1 #> # A tibble: 4 × 1 #> n #> <chr> #> 1 -- #> 2 orange #> 3 banana #> 4 -- #> #> $x2 #> # A tibble: 4 × 1 #> n #> <chr> #> 1 -- #> 2 orange #> 3 banana #> 4 --
改用reframe后结果仍一致,请问正确实现方法是什么?
正确实现方法
你的错误在于summarise的语法使用不当:.by参数应该作为summarise的顶层参数,而非放在across内部;同时across里的逻辑错误,误将fruits的标签赋值给了n列。
以下是两种简洁的实现方式:
方法一:保留所有分组的聚合
直接按fruits分组,对n列求和,会保留所有分组(包括"--"、"orange"、"banana"):
df2 |> purrr::map(\(x) { x |> dplyr::summarise(n = sum(n), .by = fruits) })
输出结果:
#> $x1 #> # A tibble: 3 × 2 #> fruits n #> <chr> <int> #> 1 -- 5 #> 2 orange 3 #> 3 banana 2 #> #> $x2 #> # A tibble: 3 × 2 #> fruits n #> <chr> <int> #> 1 -- 14 #> 2 orange 5 #> 3 banana 7
方法二:仅聚合指定分组
如果只需要"--"分组的求和结果,可以先筛选再聚合:
df2 |> purrr::map(\(x) { x |> dplyr::filter(fruits == "--") |> dplyr::summarise(fruits = "--", n = sum(n)) })
输出结果:
#> $x1 #> # A tibble: 1 × 2 #> fruits n #> <chr> <int> #> 1 -- 5 #> #> $x2 #> # A tibble: 1 × 2 #> fruits n #> <chr> <int> #> 1 -- 14
补充说明
如果习惯传统分组写法,也可以用group_by + summarise实现,效果和方法一一致:
df2 |> purrr::map(\(x) { x |> dplyr::group_by(fruits) |> dplyr::summarise(n = sum(n)) |> dplyr::ungroup() })
内容的提问来源于stack exchange,提问作者ryoto
相关产品推荐
相关产品推荐

