【问题标题】:Look for various quantiles in a function list in an efficient way?以有效的方式在函数列表中查找各种分位数?
【发布时间】:2019-11-14 09:40:09
【问题描述】:

我已经尝试多次调用分位数,但考虑到我需要 0.05 的分位数增量并且我的数据非常大,这非常低效。

ff <- function(table, IDs, q.increment=0.05){
  fun <- list("mean" = function(x) mean(x, na.rm = TRUE),
              "median" = function(x) median(x, na.rm =TRUE),
              function(x) quantile(x, probs = seq(0, 1, q.increment), na.rm=T))

  fun.names <- names(fun)
  abc <- table[ , c(summary = list(fun.names),
                    lapply(.SD, function(col) I(lapply(fun, function(f) f(col))))),
                by = IDs, .SDcols = grep("value", names(table))]
  return(abc)
}

dt <- data.table(country = c("FR", "US", "HU", "HU", "FR", "FR", "US", "US", "US", "HU"), value1=rnorm(10), value2=rnorm(10))
abc <- ff(dt, c("country"))

我不喜欢的是分位数都在一个单元格中,我希望每个分位数都有一行。

【问题讨论】:

    标签: r statistics data.table summary quantile


    【解决方案1】:

    执行此操作的方法是将quantile 转换为list,然后unlisting 使用recursive = FALSE

    dt[, c(unlist(lapply(.SD, function(x) list(mean = mean(x),
        median = median(x))), recursive = FALSE), 
       unlist(lapply(.SD, function(x) as.list(quantile(x,
       probs = seq(0, 1, 0.05)))), recursive = FALSE)), country]
    

    它可以被包装在一个函数中

    ff1 <- function(data, IDs, q.increment = 0.05) {
        f1 <- function(x) list(mean = mean(x, na.rm = TRUE),
                               median = median(x, na.rm = TRUE),
                               quantile = as.list(quantile(x, 
                    probs = seq(0, 1, q.increment))))
    
    
         data[, unlist(unlist(lapply(.SD, f1), recursive = FALSE),
               recursive = FALSE), by = IDs, .SDcols = grep("value", names(data))]
     }
    
    out <- ff1(dt, "country")
    

    如果我们需要长格式,则使用melt

    nm1 <- unique(sub(".*\\.", "", names(out)[-1]))
    melt(out, measure = patterns('^value1', '^value2'),
          variable.name = 'summary')[, summary := nm1[summary]][]
    # country summary      value1      value2
    # 1:      FR    mean -0.70362861 -0.37004727
    # 2:      US    mean -0.17024421 -0.10986835
    # 3:      HU    mean  0.35754440  0.43067053
    # 4:      FR  median -0.25453398 -0.72539656
    # 5:      US  median -0.08068703  0.15472558
    # 6:      HU  median  0.61732639  0.30846369
    # 7:      FR      0% -1.60473855 -1.34258692
    # 8:      US      0% -0.87641285 -2.04386860
    # 9:      HU      0% -0.37871048  0.08147549
    #10:      FR      5% -1.46971809 -1.28086789
    #11:      US      5% -0.80765939 -1.72964937
    #...
    

    【讨论】:

    • 很好的答案。我一直在寻找最后一步。只是一个额外的问题。假设我有 100 个值名称 value1、value2、...、value100。我应该如何在不改变结果的情况下修改模式?
    • @G.Bartowski 你可以用pastepaste0("^value", 1:100)创建一个向量
    • @G.Bartowski 即melt(out, measure = patterns(paste0("^value", 1:100)))
    • 哦,太好了。它们不完全是连续的,但我可以做到这一点measure = patterns(paste0("^", names(data)[grep("value", names(data))]))
    猜你喜欢
    • 1970-01-01
    • 2015-07-07
    • 2012-07-23
    • 1970-01-01
    • 1970-01-01
    • 2019-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多