2

这个问题是对这里提出和回答的 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)

有没有一种好方法可以优化计算每个值的百分位数的过程?本质上,我想让它尽可能高效,以便运行时间尽可能短。

4

2 回答 2

4

ecdf已经矢量化,没有理由使用apply函数。您可以简单地运行:

df$val.percentile <- ecdf(df$val)(df$val)
于 2016-12-11T15:11:38.993 回答
3

您可以实施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)

在此处输入图像描述

于 2016-12-11T14:33:42.803 回答