首页 > 解决方案 > 考虑分组数据中时间戳的秩计算

问题描述

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

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

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

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

有人有想法吗?

标签: rdplyrpanelrankpercentile

解决方案


首先,我会使用complete这样每个player/date_sec组合都有一行。这将允许更容易地比较每个时刻。

接下来,我将使用fill每个玩家的最新分数结转。在此之前应对分数进行排序/排列。

然后,由于您对每个时间戳都有一个分数,因此您可以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

推荐阅读