【发布时间】: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,但是如果在同一天有重复的值被其他值分隔,那将不起作用。
我还想过按date 和id 进行分组,然后使用组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 中。
【问题讨论】: