14

With data structured as follows...

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

I'm having a tough time creating a growth rate column (by year) within category. Can anyone help with code to create something like this...

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  
4

7 回答 7

17

对于这类问题(“我如何按 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))是取对数的差异,即log(x[t+1])-log(x[t])全部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()了一些额外的“语法糖”,以避免创建新的匿名函数。

于 2013-11-06T23:05:04.993 回答
7

使用 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)))
于 2013-11-06T23:09:35.637 回答
6

您可以简单地使用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
于 2018-12-03T03:43:00.997 回答
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是主力,分割和计算增长率的函数由该函数的参数定义。

于 2013-11-06T23:04:52.113 回答
3

基于 Ben 的想法的更优雅的变体,在我的 R 包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那样的滞后差异)。

于 2013-11-14T12:43:32.123 回答
0

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 / Gplm 包中还提供了plm::pseries和类的方法。plm::pdata.frame

于 2020-04-16T10:17:11.090 回答
0

许多年后: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
于 2019-08-17T10:45:37.887 回答