【问题标题】:Grouped non-dense rank without omitted values没有遗漏值的分组非密集秩
【发布时间】:2020-05-09 00:27:11
【问题描述】:

我有以下data.frame:

df <- data.frame(date = c(1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3),
                 id   = c(4, 4, 2, 4, 1, 2, 3, 1, 2, 2, 1, 1))

我想添加一个新列grp,它为每个日期对 ID 进行排名。关系应具有相同的值,但不应有遗漏的值。也就是说,如果有两个同样最小的值,它们都应该得到 1 级,而下一个最低值应该得到 2 级。

因此,预期结果将如下所示。请注意,如上所述,组是针对每个日期的,因此操作必须按日期分组。

data.frame(date = c(1, 1, 1, 1,     2, 2, 2, 2,     3, 3, 3, 3),
           id   = c(4, 4, 2, 4,     1, 2, 3, 1,     2, 2, 1, 1),
           grp  = c(2, 2, 1, 2,     1, 2, 3, 1,     2, 2, 1, 1))

我确信有一种简单的方法可以做到这一点,但我还没有找到:tie.method 的所有选项都不会以这种方式运行(data.table::frank 也无济于事,因为它只会增加密集排名)。

我想过做一个正常的排名,然后使用data.table::rleid,但是如果在同一天有重复的值被其他值分隔,那将不起作用。

我还想过按dateid 进行分组,然后使用组ID,但每天的最低值必须从排名1 开始,这样也行不通。

我发现的唯一功能性解决方案是每天创建另一个具有唯一 ids 的表,然后将该表加入该表:

suppressPackageStartupMessages(library(dplyr))

df <- data.frame(date = c(1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3),
                 id   = c(4, 4, 2, 4, 1, 2, 3, 1, 2, 2, 1, 1))

uniques <- df %>%
  group_by(
    date
  ) %>%
  distinct(
    id
  ) %>%
  mutate(
    grp = rank(id)
  )

df <- df %>% left_join(
  unique
) %>% print()
#> Joining, by = c("date", "id")
#>    date id grp
#> 1     1  4   2
#> 2     1  4   2
#> 3     1  2   1
#> 4     1  4   2
#> 5     2  1   1
#> 6     2  2   2
#> 7     2  3   3
#> 8     2  1   1
#> 9     3  2   2
#> 10    3  2   2
#> 11    3  1   1
#> 12    3  1   1

reprex package (v0.3.0) 于 2020 年 5 月 8 日创建

但是,对于看似简单的操作而言,这似乎很不优雅且令人费解,所以我宁愿看看是否有其他解决方案可用。

很想看看data.table 解决方案(如果有),但不幸的是,解决方案必须在dplyr 中。

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    我们可以使用dense_rank

    library(dplyr)
    df %>%
       group_by(date) %>%
       mutate(grp = dense_rank(id))
    # A tibble: 12 x 3
    # Groups:   date [3]
    #   date    id   grp
    #   <dbl> <dbl> <int>
    # 1     1     4     2
    # 2     1     4     2
    # 3     1     2     1
    # 4     1     4     2
    # 5     2     1     1
    # 6     2     2     2
    # 7     2     3     3
    # 8     2     1     1
    # 9     3     2     2
    #10     3     2     2
    #11     3     1     1
    #12     3     1     1
    

    frank

    library(data.table)
    setDT(df)[, grp := frank(id, ties.method = 'dense'), date]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-25
      • 2016-11-20
      • 1970-01-01
      • 2017-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多