有效地计算数据框列的百分位数
Calculate a percentile of dataframe column efficiently
此问题是对 Whosebug 问题的扩展 here。
我的情况有所不同,因为我想计算 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)
有什么好的方法可以优化计算每个值的百分位数的过程吗?本质上,我想让它尽可能高效,因此 运行 时间尽可能短。
您可以实施 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)
ecdf
已经向量化,没有理由使用 apply
函数。你可以简单地 运行:
df$val.percentile <- ecdf(df$val)(df$val)
此问题是对 Whosebug 问题的扩展 here。
我的情况有所不同,因为我想计算 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)
有什么好的方法可以优化计算每个值的百分位数的过程吗?本质上,我想让它尽可能高效,因此 运行 时间尽可能短。
您可以实施 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)
ecdf
已经向量化,没有理由使用 apply
函数。你可以简单地 运行:
df$val.percentile <- ecdf(df$val)(df$val)