【问题标题】:How calculate growth rate in long format data frame?如何计算长格式数据框中的增长率?
【发布时间】:2013-11-06 22:56:21
【问题描述】:

数据结构如下...

df <- data.frame(Category=c(rep("A",6),rep("B",6)),
      Year=rep(2010:2015,2),Value=1:12)

我很难在类别内创建一个增长率列(按年份)。任何人都可以帮助编写代码来创建这样的东西......

Category Year Value Growth  
    A   2010    1   
    A   2011    2   1.000  
    A   2012    3   0.500  
    A   2013    4   0.333  
    A   2014    5   0.250  
    A   2015    6   0.200  
    B   2010    7     
    B   2011    8   0.143  
    B   2012    9   0.125  
    B   2013    10  0.111  
    B   2014    11  0.100  
    B   2015    12  0.091  

【问题讨论】:

    标签: r math dataframe


    【解决方案1】:

    对于这类问题(“我如何按 YYY 类别计算 XXX”)?总是有基于by()data.table() 包和plyr 的解决方案。我通常更喜欢plyr,它通常速度较慢,但​​(对我而言)更透明/优雅。

    df <- data.frame(Category=c(rep("A",6),rep("B",6)),
      Year=rep(2010:2015,2),Value=1:12)
    
    
    library(plyr)
    ddply(df,"Category",transform,
             Growth=c(NA,exp(diff(log(Value)))-1))
    

    这个答案和@krlmr 的主要区别在于我使用了几何平均技巧(取对数的差异,然后求幂),而@krlmr 计算一个明确的比率。

    从数学上讲,diff(log(Value)) 正在计算日志的差异,即所有tlog(x[t+1])-log(x[t])。当我们取幂时,我们得到比率x[t+1]/x[t](因为exp(log(x[t+1])-log(x[t])) = exp(log(x[t+1]))/exp(log(x[t])) = x[t+1]/x[t])。 OP想要分数变化而不是乘法增长率(即x[t+1]==x[t]对应于零的分数变化而不是1.0的乘法增长率),所以我们减去1。

    我还使用transform() 来添加一点额外的“语法糖”,以避免创建新的匿名函数。

    【讨论】:

    • 什么什么?你能再让我使用explog吗??
    • @SlowLearner:log(a/b) = log(a) - log(b)。现在申请exp。
    • 我想知道:是否有更通用的 diff 函数可以接受双参数函数作为参数?
    • 现在有:kimisc::gdiff。见my other answer
    • 我喜欢这个并且想指出diff 函数需要一个lag 参数。因此,对于季度数据,可以定义像 f &lt;- function(x, lag=1) c(rep(NA,lag), exp(diff(log(x),lag=lag))-1) 这样的函数,并将其与 lag=4 一起使用。
    【解决方案2】:

    使用 R 基函数 (ave)

    > dfdf$Growth <- with(df, ave(Value, Category, 
                          FUN=function(x) c(NA, diff(x)/x[-length(x)]) ))
    > df
       Category Year Value     Growth
    1         A 2010     1         NA
    2         A 2011     2 1.00000000
    3         A 2012     3 0.50000000
    4         A 2013     4 0.33333333
    5         A 2014     5 0.25000000
    6         A 2015     6 0.20000000
    7         B 2010     7         NA
    8         B 2011     8 0.14285714
    9         B 2012     9 0.12500000
    10        B 2013    10 0.11111111
    11        B 2014    11 0.10000000
    12        B 2015    12 0.09090909
    

    @Ben Bolker 的回答很容易适应ave

    transform(df, Growth=ave(Value, Category, 
                             FUN=function(x) c(NA,exp(diff(log(x)))-1)))
    

    【讨论】:

      【解决方案3】:

      您可以简单地使用dplyr 包:

      > df %>% group_by(Category) %>% mutate(Growth = (Value - lag(Value))/lag(Value))  
      

      这将产生以下结果:

      # A tibble: 12 x 4
      # Groups:   Category [2]
         Category  Year Value  Growth
         <fct>    <int> <int>   <dbl>
       1 A         2010     1 NA     
       2 A         2011     2  1     
       3 A         2012     3  0.5   
       4 A         2013     4  0.333 
       5 A         2014     5  0.25  
       6 A         2015     6  0.2   
       7 B         2010     7 NA     
       8 B         2011     8  0.143 
       9 B         2012     9  0.125 
      10 B         2013    10  0.111 
      11 B         2014    11  0.1   
      12 B         2015    12  0.0909
      

      【讨论】:

        【解决方案4】:

        plyr 非常简单:

        library(plyr)
        ddply(df, .(Category),
              function (d) {
                d$Growth <- c(NA, tail(d$Value, -1) / head(d$Value, -1) - 1)
                d
              }
        )
        

        这里有两个问题:

        1. 按类别划分
        2. 计算增长率

        ddply 是主力,分割和计算增长率的函数由该函数的参数定义。

        【讨论】:

        • 你领先我 12 秒。我喜欢我的几何平均 (diff(log(x))) 方法,但你的方法也有效。
        【解决方案5】:

        基于 Ben 的想法的更优雅的变体,在 my R package 中使用新的 gdiff 函数:

        df <- data.frame(Category=c(rep("A",6),rep("B",6)),
          Year=rep(2010:2015,2),Value=1:12)
        
        library(plyr)
        ddply(df, "Category", transform,
              Growth=c(NA, kimisc::gdiff(Value, FUN = `/`)-1))
        

        这里,gdiff 用于计算滞后率(而不是 diff 那样的滞后差异)。

        【讨论】:

          【解决方案6】:

          多年后:tsbox 包旨在处理所有类型的时间序列对象,包括数据帧,并提供标准时间序列工具包。因此,计算增长率很简单:

          df <- data.frame(Category=c(rep("A",6),rep("B",6)),
                Year=rep(2010:2015,2),Value=1:12)
          
          library(tsbox)
          ts_pc(df)
          #> [time]: 'Year' [value]: 'Value' 
          #>    Category       Year      Value
          #> 1         A 2010-01-01         NA
          #> 2         A 2011-01-01 100.000000
          #> 3         A 2012-01-01  50.000000
          #> 4         A 2013-01-01  33.333333
          #> 5         A 2014-01-01  25.000000
          #> 6         A 2015-01-01  20.000000
          #> 7         B 2010-01-01         NA
          #> 8         B 2011-01-01  14.285714
          #> 9         B 2012-01-01  12.500000
          #> 10        B 2013-01-01  11.111111
          #> 11        B 2014-01-01  10.000000
          #> 12        B 2015-01-01   9.090909
          

          【讨论】:

            【解决方案7】:

            CRAN 中的包collapse 为此类问题提供了一种简单且完全基于C/C++ 的解决方案:使用通用函数fgrowth 和相关的增长运算符G

            df <- data.frame(Category=c(rep("A",6),rep("B",6)),
                  Year=rep(2010:2015,2),Value=1:12)
            
            library(collapse)
            G(df, by = ~Category, t = ~Year)
            
               Category Year   G1.Value
            1         A 2010         NA
            2         A 2011 100.000000
            3         A 2012  50.000000
            4         A 2013  33.333333
            5         A 2014  25.000000
            6         A 2015  20.000000
            7         B 2010         NA
            8         B 2011  14.285714
            9         B 2012  12.500000
            10        B 2013  11.111111
            11        B 2014  10.000000
            12        B 2015   9.090909
            
            # fgrowth is more of a programmers function, you can do:
            
            fgrowth(df$Value, 1, 1, df$Category, df$Year)
             [1]   NA 100.000000  50.000000  33.333333  25.000000  20.000000         NA  14.285714  12.500000  11.111111  10.000000   9.090909
            
            # Which means: Calculate the growth rate of Value, using 1 lag, and iterated 1 time (you can compute arbitrary sequences of lagged / leaded and iterated growth rates with these functions), identified by Category and Year.
            

            fgrowth / G 还具有 plm 包中可用的 plm::pseriesplm::pdata.frame 类的方法。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多