高效计算数据框列的百分位数

3

这个问题是对StackOverflow上一个问题的扩展,该问题已经在这里得到了回答。

我的情况与众不同,我想计算一个包含50,000个或更多值的向量中每个值的百分位数。例如--

df <- data.frame(val = rnorm(n = 50000, mean = 50, sd = 20))
df$val.percentile <- sapply(X = df$val, function(x) ecdf(df$val)(x))
head(df)

有没有一种好的方法来优化计算每个值的百分位数的过程?本质上,我希望尽可能地提高效率,使运行时间尽可能短。

2个回答

5

ecdf已经向量化,没有必要使用apply函数。您只需运行:

df$val.percentile <- ecdf(df$val)(df$val)

这个答案和我的有什么不同? - IRTFM
@42- 不是的,但你和巴克几乎同时发布了(巴克是第一个)。 - Jaap
哦,我在发布(或编辑)时没有看到它。我以为它是后来出现的。 - IRTFM

4
你可以使用 dplyr::percent_rank() 实现基于百分位数的排名。然而,这与基于累积分布函数确定排名有所不同 dplyr::cume_dist() (小于或等于当前排名的所有值的比例)。
可重现的示例:
set.seed(1)
df <- data.frame(val = rnorm(n = 1000000, mean = 50, sd = 20))

展示percent_rank()cume_dist()的不同之处,并且cume_dist()ecdf(x)(x)相同:

library(tidyverse)

head(df) %>% 
  mutate(pr  = percent_rank(val), 
         cd  = ecdf(val)(val), 
         cd2 = cume_dist(val))

       val  pr        cd       cd2
1 37.47092 0.4 0.5000000 0.5000000
2 53.67287 0.6 0.6666667 0.6666667
3 33.28743 0.0 0.1666667 0.1666667
4 81.90562 1.0 1.0000000 1.0000000
5 56.59016 0.8 0.8333333 0.8333333
6 33.59063 0.2 0.3333333 0.3333333

这个示例数据集的每种方法速度大致相似,没有超过2倍的因素:

library(microbenchmark)
mbm <- microbenchmark(
    pr_dplyr = mutate(df, pr = percent_rank(val)),
    cd_dplyr = mutate(df, pr = percent_rank(val)),
    cd_base  = mutate(df, pr = ecdf(val)(val)),
    times = 20
)

autoplot(mbm)

enter image description here


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