Как рассчитать темпы роста в формате длинного формата?

С данными, структурированными следующим образом...

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  

Ответ 1

Для таких вопросов ( "как я могу вычислить XXX по категории YYY" )? всегда существуют решения на основе 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]). ОР хотел, чтобы дробное изменение, а не мультипликативная скорость роста (т.е. x[t+1]==x[t] соответствует дробному изменению нуля, а не мультипликативной скорости роста 1,0), поэтому мы вычитаем 1.

Я также использую transform() для немного дополнительного "синтаксического сахара", чтобы избежать создания новой анонимной функции.

Ответ 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

Очень легко с plyr:

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

Здесь у нас две проблемы:

  • Разделение по категориям
  • Вычисление темпа роста

ddply - рабочая лошадка, разделение и функция для вычисления скорости роста определяются параметрами этой функции.

Ответ 4

Более элегантный вариант, основанный на идее Бена с новой функцией gdiff в мой пакет R:

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).

Ответ 5

Вы можете просто использовать пакет 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

Ответ 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