使用dplyr::percent_rank()函数计算组内的百分位排名

14

假设我有以下数据:

id    grpvar1    grpvar2    value
1     1          3          7.6
2     1          2          4
...
3     1          5          2
对于每个id,我想计算其在由grpvar1grpvar2组合定义的组内value百分比排名percent_rank()
使用data.table,我会这样做(假设我的数据在名为datafdata.frame中):
library(data.table)

# Make dataset into a data.table.
dt <- data.table(dataf)

# Calculate the percentiles.
dt[, percrank := rank(value)/length(value), by = c("grpvar1", "grpvar2")]

dplyr中,相当于什么?


2
你可以尝试使用以下代码:dataf %>% group_by(grpvar1, grpvar2) %>% mutate(percrank=rank(value)/length(value)) 这段代码会给出与使用data.table时展示的输出相同的结果。 - akrun
3
使用 dplyr::percent_rank() 没有实际的理由,因为它只是一个简单的函数,执行的操作与 (min_rank(x) - 1)/(length(x) - 1) 相同。与尝试采用 percent_rank 的方式相比,编写 rank(value)/length(value) 更容易。 - David Arenburg
1
Akrun,把它写在一个答案里,一旦我确认它按照我的意愿工作,就会检查它! - Brash Equilibrium
1
@Brash Equilibrium 谢谢,我把它发布为解决方案。 - akrun
1
为什么公式是min_rank(x)-1/length(x)-1?我不理解“-1”部分的含义。 - user798719
1个回答

15

尝试:

 library(dplyr)
 dataf %>%
 group_by(grpvar1, grpvar2) %>% 
 mutate(percrank=rank(value)/length(value))

如果在一个包含数百万行和成千上万个组的Postgres数据库中处理外部数据集,这可能会非常缓慢,对吗? - Brash Equilibrium
1
@Brash Equilibrium 是的,我同意。如果数据集可管理,data.table 将是更快的选项。 - akrun
如果一次性将整个数据集全部导入可能会变得难以管理。我需要只导入进行排名所需的数据,然后在排名后的聚合步骤中清除垃圾数据。 - Brash Equilibrium
我在谈论dplyr查询构建能力,以及如何有时候在内存中处理比在数据库中更快,但这也意味着需要花费时间清理垃圾。 - Brash Equilibrium
@BrashEquilibrium 做基准测试 - 如果你的索引设置正确,PostgreSQL 可能能够大幅度优化查询。 - hadley
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接