如何使用summarise_at将不同的函数应用于不同的列?

时间:2018-07-31 17:25:22

标签: r dplyr

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

> 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列中,这些列在按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

2 个答案:

答案 0 :(得分:4)

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

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

第二个是您可以使用{}来将%>%的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-07-31创建。

答案 1 :(得分:0)

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

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