【问题标题】:nth lowest value from from previous k values前 k 个值中的第 n 个最小值
【发布时间】:2021-03-04 23:56:47
【问题描述】:

我有以下数据表(使用 data.table 包)。

Month   ER
196307  -0.39359311
196308  5.06729343
196309  -1.56222299
196310  2.53955005
196311  -0.85428909

对于每一行,我想添加一个列VR,它的前三个值ER 中的第二高值。例如 196311 为 2.53955,196310 为 -0.39359311。

【问题讨论】:

    标签: r sorting data.table


    【解决方案1】:

    data.table可以使用frollapply进行滚动计算。

    library(data.table)
    
    n <- 2
    
    setDT(df)[, VR := frollapply(shift(ER), 4, 
                        function(x) sort(x, decreasing = TRUE)[n], fill = NA)]
    df
    
    #    Month     ER     VR
    #1: 196307 -0.394     NA
    #2: 196308  5.067     NA
    #3: 196309 -1.562     NA
    #4: 196310  2.540 -0.394
    #5: 196311 -0.854  2.540
    

    【讨论】:

      【解决方案2】:

      (@akrun 比我快几秒钟。)不确定你是否有文字 data.table(即,在 data.table 包中):无论如何,rollapply(来自 zoo,如果你有“常规”数据)或frollapply(如果您使用的是data.table)...

      dd <- read.table(header=TRUE, text="
      Month   ER
      196307  -0.39359311
      196308  5.06729343
      196309  -1.56222299
      196310  2.53955005
      196311  -0.85428909
      ")
      
      library(zoo)
      
      dd$VR <- rollapply(dd$ER, width=4, FUN= function(x) sort(x[-4])[2],
                         fill=NA, align="right")
      ## [1]         NA         NA         NA -0.3935931  2.5395500
      

      由于rollapply 包含当前值,为了获得先前 3 个值中第二高的值,我一次取四个值并忽略第四个(x[-4]); @akrun 的解决方案使用 lag() 代替(这似乎稍微好一点,尽管它确实会导致对 tidyverse 的依赖,这可能是您不想要的)。

      @akrun 的解决方案也按-x 排序(颠倒顺序):在这种情况下,由于您指定了三个值中的第二高值,因此您按哪个顺序排序并不重要,但您的问题标题 ( "前 k 中第 n 低") 确实表明反向排序是一个好主意。

      【讨论】:

      • 谢谢。您知道可以使用 data.table 包完成此操作的方法吗?
      • 建议rollapply(dd$ER, list(-(1:3)), sort, fill = NA)[, 2] 其中list(-(1:3)) 指定仅使用指定的偏移量。这给出了一个矩阵,每一行都排序,所以我们取第二列。
      【解决方案3】:

      我们可以使用zoo中的rollapply

      library(zoo)
      library(dplyr)
      df1 %>%
          mutate(VR = rollapply(lag(ER), 3,
               FUN = function(x) x[order(-x)][2], fill = NA, align = 'right'))
      

      【讨论】:

        【解决方案4】:

        这是另一个使用非等连接的选项:

        DT[, c("start", "end") := .(Month-3L, Month-1L)]
        DT[order(ER)][DT, on=.(Month>=start, Month<=end),
            .(Month=i.Month, ER=i.ER, VALUE=x.ER)][
                order(Month, ER), .(VR=VALUE[2L]), .(Month, ER)]
        

        输出:

            Month         ER         VR
        1: 196307 -0.3935931         NA
        2: 196308  5.0672934         NA
        3: 196309 -1.5622230  5.0672934
        4: 196310  2.5395500 -0.3935931
        5: 196311 -0.8542891  2.5395500
        

        数据:

        library(data.table)
        DT <- fread("Month   ER
        196307  -0.39359311
        196308  5.06729343
        196309  -1.56222299
        196310  2.53955005
        196311  -0.85428909")
        

        【讨论】:

          猜你喜欢
          • 2014-03-16
          • 1970-01-01
          • 2021-01-06
          • 2011-02-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-04-24
          • 1970-01-01
          相关资源
          最近更新 更多