分组数据中考虑时间戳的排名计算

Rank computation considering time stamp in grouped data

在我的游戏数据集中,我有几个游戏玩家在几个时间点的观察结果。对于每次观察,我想根据此时点数与其他玩家的点数相比,计算该玩家的排名。因此,它必须将这次观察的这个玩家的点数与所有其他玩家在他们最后一次(或过去时间上最接近的或恰好在同一秒)观察其他每个用户的点数进行比较。

包含预期排名的示例数据:

da = data.frame(player = c(1,1,1,2,2,2,3,3,3), date_sec = c(1451665633,1451665693,1451665721,1451665627,1451665692,1451665738,1451665626,1451665684,1451665765), points = c(100,150,200,130,140,230,80,90,100), rank = c(2,1,1,1,1,1,1,3,3))

da
  player   date_sec points rank
1      1 1451665633    100    2
2      1 1451665693    150    1
3      1 1451665721    200    1
4      2 1451665627    130    1
5      2 1451665692    140    1
6      2 1451665738    230    1
7      3 1451665626     80    1
8      3 1451665684     90    3
9      3 1451665765    100    3

例如,玩家 2 在 date_sec 1451665738 排名 1,因为在这个时间点,没有其他玩家有更多的分数。

我知道如何在组内排名,但我没有找到一种方法来考虑准确的时间点。一种方法是从时间戳中提取日期并按日期和玩家分组,但这并不像我希望的那样准确,因为排名可以在一天内更改多次。

library(dplyr)

da2 = mutate(da, day = as.Date(as.POSIXct(date_sec, origin="1970-01-01"))) %>%
   group_by(player, day) %>%
   mutate(my_ranks = order(order(points, day, decreasing=TRUE)))

da2

A tibble: 9 x 6
# Groups:   player, day [3]
  player   date_sec points  rank day        my_ranks
   <dbl>      <dbl>  <dbl> <dbl> <date>        <int>
1      1 1451665633    100     2 2016-01-01        3
2      1 1451665693    150     1 2016-01-01        2
3      1 1451665721    200     1 2016-01-01        1
4      2 1451665627    130     1 2016-01-01        3
5      2 1451665692    140     2 2016-01-01        2
6      2 1451665738    230     2 2016-01-01        1
7      3 1451665626     80     3 2016-01-01        3
8      3 1451665684     90     3 2016-01-01        2
9      3 1451665765    100     3 2016-01-01        1

除了排名,我还想有一个基于积分的百分位排名,因为不同时间段活跃的玩家数量不同。

有人知道吗?

首先,我会使用 complete,这样每个 player/date_sec 组合都有一行。这样可以更轻松地及时比较每个时刻。

接下来,我将使用 fill 结转每个玩家的最近得分。在此之前的分数应该是sorted/arranged

然后,因为你有每个时间戳的分数,你可以group_by(date_sec)和排序每个时间的球员进行排名。

最后,您可以重新加入原始数据框以提供所需的排名。

library(tidyverse)

da %>%
  complete(player, date_sec) %>%
  group_by(player) %>%
  arrange(date_sec) %>%
  fill(points) %>%
  group_by(date_sec) %>%
  mutate(my_ranks = order(order(points, decreasing = TRUE))) %>%
  right_join(da)

输出

Joining, by = c("player", "date_sec", "points", "rank")
# A tibble: 9 x 5
# Groups:   date_sec [9]
  player   date_sec points  rank my_ranks
   <dbl>      <dbl>  <dbl> <dbl>    <int>
1      1 1451665633    100     2        2
2      1 1451665693    150     1        1
3      1 1451665721    200     2        1
4      2 1451665627    130     1        1
5      2 1451665692    140     2        1
6      2 1451665738    230     1        1
7      3 1451665626     80     3        1
8      3 1451665684     90     3        3
9      3 1451665765    100     3        3