【问题标题】:Calculate a percentile of dataframe column efficiently有效计算数据框列的百分位数
【发布时间】:2017-04-26 12:15:34
【问题描述】:

此问题是对 here 提出和回答的 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)

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

【问题讨论】:

    标签: r dataframe quantile ecdf


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 这个答案和我的有什么不同?
      • @42- 不是,但你和巴克几乎同时发帖(巴克是第一个)
      • 呵呵,我发帖(或编辑)时没看到。我以为它后来来了。
      猜你喜欢
      • 2014-02-08
      • 1970-01-01
      • 2020-10-07
      • 2013-08-15
      • 2011-12-29
      • 2013-06-20
      • 1970-01-01
      • 2017-12-03
      相关资源
      最近更新 更多