【问题标题】:How can I use summarise_at to apply different functions to different columns?如何使用 summarise_at 将不同的函数应用于不同的列?
【发布时间】:2018-07-31 17:25:22
【问题描述】:

我有一个包含以下列的数据框:

> colnames(my.dataframe)
 [1] "id"                              "firstName"                       "lastName"                       
 [4] "position"                        "jerseyNumber"                    "currentTeamId"                  
 [7] "currentTeamAbbreviation"         "currentRosterStatus"             "height"                         
[10] "weight"                          "birthDate"                       "age"                            
[13] "birthCity"                       "birthCountry"                    "rookie"                         
[16] "handednessShoots"                "college"                         "twitter"                        
[19] "currentInjuryDescription"        "currentInjuryPlayingProbability" "teamId"                         
[22] "teamAbbreviation"                "fg2PtAtt"                        "fg3PtAtt"                       
[25] "fg2PtMade"                       "fg3PtMade"                       "ftMade"                         
[28] "fg2PtPct"                        "fg3PtPct"                        "ftPct"                          
[31] "ast"                             "tov"                             "offReb"                         
[34] "foulsDrawn"                      "blkAgainst"                      "plusMinus"                      
[37] "minSeconds"

这是我的代码不起作用:

my.dataframe %>%
  dplyr::group_by(id) %>%
  dplyr::summarise_at(vars(firstName:currentInjuryPlayingProbability), funs(min), na.rm = TRUE) %>%
  dplyr::summarise_at(vars(fg2PtAtt:minSeconds), funs(sum), na.rm = TRUE) %>% 
                    vars(), funs(min), na.rm = TRUE) %>%
  dplyr::summarise(teamId = paste(teamId), teamAbbreviation = paste(teamAbbreviation)) 

首先我按 id 分组(这不是我的数据框中的唯一列,尽管它被称为 id)。对于直到 currentInjuryPlayingProbability 的接下来的 19 列,这些列在 grouped_by ID 时总是相同的,因此我使用min 函数来汇总/获取值。

接下来,我想用平均值总结从fg2PtAtt 到末尾的所有列(这些列都是数字/整数)。

最后,对于列 teamId 和 teamAbbreviation(在 grouped_by id 时不一样),我想将它们粘贴到一个单独的字符串中,每个字符串都有摘要。

我的方法不起作用,因为我认为我不能调用 summarise_at,然后调用另一个 summarise_at,然后再调用 summarise。在调用第二个 summarise_at 时,试图汇总的列已被第一个 summarise_at 删除

对此的任何帮助表示赞赏!我将很快更新我的数据帧的一个子集,以便测试代码。

编辑:

dput(my.dataframe)
structure(list(id = c(10138L, 9466L, 9360L, 9360L), firstName = c("Alex", 
"Quincy", "Luke", "Luke"), lastName = c("Abrines", "Acy", "Babbitt", 
"Babbitt"), currentInjuryPlayingProbability = c(NA_character_, 
NA_character_, NA_character_, NA_character_), teamId = c(96L, 
84L, 91L, 92L), teamAbbreviation = c("OKL", "BRO", "ATL", "MIA"
), fg2PtAtt = c(70L, 73L, 57L, 2L), fg3PtAtt = c(221L, 292L, 
111L, 45L), minSeconds = c(67637L, 81555L, 34210L, 8676L)), row.names = c(NA, 
-4L), class = c("tbl_df", "tbl", "data.frame"))

my.dataframe
     id firstName lastName currentInjuryPlayingProbability teamId teamAbbreviation fg2PtAtt fg3PtAtt minSeconds
  <int> <chr>     <chr>    <chr>                            <int> <chr>               <int>    <int>      <int>
1 10138 Alex      Abrines  <NA>                                96 OKL                    70      221      67637
2  9466 Quincy    Acy      <NA>                                84 BRO                    73      292      81555
3  9360 Luke      Babbitt  <NA>                                91 ATL                    57      111      34210
4  9360 Luke      Babbitt  <NA>                                92 MIA                     2       45       8676

这是一个只有 9 列的简短示例,但有足够的数据来突出问题。生成的数据框应如下所示:

    id firstName lastName currentInjuryPlayingProbability teamId teamAbbreviation fg2PtAtt fg3PtAtt minSeconds
  <int> <chr>     <chr>    <chr>                            <chr>     <chr>               <int>    <int>      <int>
1 10138 Alex      Abrines  <NA>                                96      OKL                    70      221      67637
2  9466 Quincy    Acy      <NA>                                84      BRO                    73      292      81555
3  9360 Luke      Babbitt  <NA>                            91, 92 ATL, MIA                     57      156      42886

【问题讨论】:

  • 在第一个 summarise_at 之后,您会得到一个汇总输出,第二个正在调用该汇总输出。我认为更好的选择是首先调用mutate_at,然后在 group_by 中使用它,然后再进行 summarise_at。无论如何,一个可重复的小例子会有所帮助
  • 刚刚发布了一个可重现的小例子。
  • 是的,我注意到 summarise_at 发生了这种情况 - 只是不知道如何解决它
  • 看起来像 mutate_at(),然后删除重复的列,可能会成功
  • 我认为您可能想使用mutate_at,因为summarize 具有破坏性。来自?summarizeEach summary call removes one grouping level (since that group is now just a single row)Note that with data frames, newly created summaries immediately overwrite existing variables

标签: r dplyr


【解决方案1】:

这是我认为完成此特定任务的最简单方法,至少与我见过的一些类似的map2/reduce 解决方案相比。

第一点是,如果您使用min 来获取一个值,因为您认为分组变量的每个值都应该相同,只需将其添加到分组中即可。然后自动保存。

其次,您可以使用{}%&gt;% 的LHS 自动放置到RHS 的第一个参数中。这使您可以在一个步骤中应用不同的转换并重新组合它们。通常你不需要这个,因为占位符 . 会为你做这件事,但如果占位符不是 RHS 的一个赤裸裸的参数,你有时需要它。 (我确定我阅读了一些描述确切规则的资源,但我现在找不到)。

第三,因为您知道summarise 会删除除分组变量之外您未选择的列,left_join 将自动使用共享列名称加入。

这意味着我们可以执行以下操作,我认为这很干净。但是,如果转换开始变得特别复杂(例如 left_join 内是否有管道,我建议为最终输出的每一部分赋予其自己的分配和名称,以便更清楚。如果你想要更多,你还需要小心而不是同一列的一个摘要(如均值和标准差),因为写出来的名称会发生​​冲突。

library(tidyverse)

my_dataframe <- structure(list(id = c(10138L, 9466L, 9360L, 9360L), firstName = c("Alex", "Quincy", "Luke", "Luke"), lastName = c("Abrines", "Acy", "Babbitt", "Babbitt"), currentInjuryPlayingProbability = c(NA_character_, NA_character_, NA_character_, NA_character_), teamId = c(96L, 84L, 91L, 92L), teamAbbreviation = c("OKL", "BRO", "ATL", "MIA"), fg2PtAtt = c(70L, 73L, 57L, 2L), fg3PtAtt = c(221L, 292L, 111L, 45L), minSeconds = c(67637L, 81555L, 34210L, 8676L)), row.names = c(NA, -4L), class = c("tbl_df", "tbl", "data.frame"))

my_dataframe %>%
  group_by_at(.vars = vars(id:lastName)) %>%
  {left_join(
    summarise_at(., vars(teamId:teamAbbreviation), ~ str_c(., collapse = ",")),
    summarise_at(., vars(fg2PtAtt:minSeconds), mean)
  )}
#> Joining, by = c("id", "firstName", "lastName")
#> # A tibble: 3 x 8
#> # Groups:   id, firstName [?]
#>      id firstName lastName teamId teamAbbreviation fg2PtAtt fg3PtAtt
#>   <int> <chr>     <chr>    <chr>  <chr>               <dbl>    <dbl>
#> 1  9360 Luke      Babbitt  91,92  ATL,MIA              29.5       78
#> 2  9466 Quincy    Acy      84     BRO                  73        292
#> 3 10138 Alex      Abrines  96     OKL                  70        221
#> # ... with 1 more variable: minSeconds <dbl>

reprex package (v0.2.0) 于 2018 年 7 月 31 日创建。

【讨论】:

    【解决方案2】:

    dplyr 1.0.2 之后更新。你可以使用across:

    summarise(across(teamId:teamAbbreviation, ~ str_c(., collapse = ",")), 
            across(fg2PtAtt:minSeconds, mean)) %>% 
    

    【讨论】:

      猜你喜欢
      • 2018-02-21
      • 2015-12-11
      • 1970-01-01
      • 1970-01-01
      • 2015-08-20
      • 1970-01-01
      • 2020-01-14
      • 2015-02-20
      • 1970-01-01
      相关资源
      最近更新 更多