使用dplyr对R中的多个列进行排序

时间:2019-02-07 23:52:04

标签: r dplyr data-manipulation

对标题不太明确的道歉-希望下面的示例有所帮助。我正在处理一些体育数据,试图为数据中的某些运动员分组计算“阵容统计”。以下是我正在使用(playerInfo)的数据类型以及我正在尝试进行的分析类型(groupedInfo)的示例:

playerInfo = data.frame(
  lineup = c(1,2,3,4,5,6),
  player1 = c("Bil", "Tom", "Tom", "Nik", "Nik", "Joe"),
  player1id = c("e91", "a27", "a27", "b17", "b17", "3b3"),
  player2 = c("Nik", "Bil", "Nik", "Joe", "Tom", "Tom"),
  player2id = c("b17", "e91", "b17", "3b3", "a27", "a27"),
  player3 = c("Joe", "Joe", "Joe", "Tom", "Joe", "Nik"),
  player3id = c("3b3", "3b3", "3b3", "a27", "3b3", "b17"),
  points = c(6, 8, 3, 12, 36, 2),
  stringsAsFactors = FALSE
)

groupedInfo <- playerInfo %>%
  dplyr::group_by(player1, player2, player3) %>%
  dplyr::summarise(
    lineup_ct = n(),
    total_pts = sum(points)
  )

> groupedInfo
# A tibble: 6 x 5
# Groups:   player1, player2 [?]
  player1 player2 player3 lineup_ct total_pts
  <chr>   <chr>   <chr>       <int>     <dbl>
1 Bil     Nik     Joe             1         6
2 Joe     Tom     Nik             1         2
3 Nik     Joe     Tom             1        12
4 Nik     Tom     Joe             1        36
5 Tom     Bil     Joe             1         8
6 Tom     Nik     Joe             1         3

这里的目标是将每一行中的3个玩家分组,然后计算不同组的一些摘要统计信息(在这个简单的示例中,是点数和总和)。不幸的是,dplyr::group_by缺少的事实是,某些玩家组应该是同一组玩家,如果只是在不同的列中有相同的3名玩家。

例如,在上面的数据框中,第3、4、5、6行都具有相同的3个玩家(Nik,Tom,Joe),但是由于有时Nik是玩家1,有时Nik是玩家2等,因此group_by将它们分别分组。

为清楚起见,以下是我要获取的结果类型的示例:

correctPlayerInfo = data.frame(
  lineup = c(1,2,3,4,5,6),
  player1 = c("Bil", "Bil", "Joe", "Joe", "Joe", "Joe"),
  player1id = c("e91", "e91", "3b3", "3b3", "3b3", "3b3"),
  player2 = c("Joe", "Joe", "Nik", "Nik", "Nik", "Nik"),
  player2id = c("3b3", "3b3", "b17", "b17", "b17", "b17"),
  player3 = c("Nik", "Tom", "Tom", "Tom", "Tom", "Tom"),
  player3id = c("b17", "a27", "a27", "a27", "a27", "a27"),
  points = c(6, 8, 3, 12, 36, 2),
  stringsAsFactors = FALSE
)

correctGroupedInfo <- correctPlayerInfo %>%
  dplyr::group_by(player1, player2, player3) %>%
  dplyr::summarise(
    lineup_ct = n(),
    total_pts = sum(points)
  )

> correctGroupedInfo
# A tibble: 3 x 5
# Groups:   player1, player2 [?]
  player1 player2 player3 lineup_ct total_pts
  <chr>   <chr>   <chr>       <int>     <dbl>
1 Bil     Joe     Nik             1         6
2 Bil     Joe     Tom             1         8
3 Joe     Nik     Tom             4        53

在第二个示例中,我已按字母顺序对数据进行了手动排序,从而使player1

如何以编程方式实现这一目标?我不确定(a)将playerInfo重组为按列排序的correctPlayerInfo(如我在上文()中所做的那样),或者(b)某些其他方法,其中group_by自动识别这些是相同的组,是否最好。

我正在为此积极努力,如果可以解决自己的问题,将发布更新。在此之前,我们将不胜感激!

编辑:到目前为止,我已经尝试了以下方法:

newPlayerInfo <- playerInfo %>%
  dplyr::mutate(newPlayer1 = min(player1, player2, player3)) %>%
  dplyr::mutate(newPlayer3 = max(player1, player2, player3))

...无济于事。

1 个答案:

答案 0 :(得分:2)

您可以创建组ID,这些组ID是玩家姓名(或ID)的排序组合。例如:

playerInfo %>% 
  mutate(
    group_id = purrr::pmap_chr(
      .l = list(p1 = player1, p2 = player2, p3 = player3),
      .f = function(p1, p2, p3) paste(sort(c(p1, p2, p3)), collapse = "_")
    )
  ) %>% 
  group_by(group_id) %>% 
  summarise(
    lineup_ct = n(),
    total_pts = sum(points)
  )

# A tibble: 3 x 3
  group_id    lineup_ct total_pts
  <chr>           <int>     <dbl>
1 Bil_Joe_Nik         1         6
2 Bil_Joe_Tom         1         8
3 Joe_Nik_Tom         4        53