Xun Zhou
Xun Zhou

Reputation: 39

calculate the growth rate for panel data

data("Grunfeld",package = "AER")
library("plm") 
gr <- subset(Grunfeld, firm %in% c("General Electric","General Motors"))
pgr <- plm.data(gr,index = c("firm","year"))

row.names   firm    year    invest  value   capital
1   1   General Motors  1935    317.6   3078.5  2.8
2   2   General Motors  1936    391.8   4661.7  52.6
3   3   General Motors  1937    410.6   5387.1  156.9
4   4   General Motors  1938    257.7   2792.2  209.2
5   5   General Motors  1939    330.8   4313.2  203.4
6   6   General Motors  1940    461.2   4643.9  207.2
7   7   General Motors  1941    512.0   4551.2  255.2
8   8   General Motors  1942    448.0   3244.1  303.7
9   9   General Motors  1943    499.6   4053.7  264.1
10  10  General Motors  1944    547.5   4379.3  201.6
11  11  General Motors  1945    561.2   4840.9  265.0
12  12  General Motors  1946    688.1   4900.9  402.2
13  13  General Motors  1947    568.9   3526.5  761.5
14  14  General Motors  1948    529.2   3254.7  922.4
15  15  General Motors  1949    555.1   3700.2  1020.1
16  16  General Motors  1950    642.9   3755.6  1099.0
17  17  General Motors  1951    755.9   4833.0  1207.7
18  18  General Motors  1952    891.2   4924.9  1430.5
19  19  General Motors  1953    1304.4  6241.7  1777.3
20  20  General Motors  1954    1486.7  5593.6  2226.3
21  41  General Electric    1935    33.1    1170.6  97.8
22  42  General Electric    1936    45.0    2015.8  104.4
23  43  General Electric    1937    77.2    2803.3  118.0
24  44  General Electric    1938    44.6    2039.7  156.2
25  45  General Electric    1939    48.1    2256.2  172.6
26  46  General Electric    1940    74.4    2132.2  186.6
27  47  General Electric    1941    113.0   1834.1  220.9
28  48  General Electric    1942    91.9    1588.0  287.8
29  49  General Electric    1943    61.3    1749.4  319.9
30  50  General Electric    1944    56.8    1687.2  321.3
31  51  General Electric    1945    93.6    2007.7  319.6
32  52  General Electric    1946    159.9   2208.3  346.0
33  53  General Electric    1947    147.2   1656.7  456.4
34  54  General Electric    1948    146.3   1604.4  543.4
35  55  General Electric    1949    98.3    1431.8  618.3
36  56  General Electric    1950    93.5    1610.5  647.4
37  57  General Electric    1951    135.2   1819.4  671.3
38  58  General Electric    1952    157.3   2079.7  726.1
39  59  General Electric    1953    179.5   2371.6  800.3
40  60  General Electric    1954    189.6   2759.9  888.9

above is the data, then I want to calculate the growth rate of invest, so the first value of General Motors' growth rate will be NA, and the General Electric's first value will be the same,that means I want to calculate the growth rate by group.

if I use the following command:

pgr$invest_growth <- NA
pgr$invest_growth<- c(NA,diff(invest)/invest[-length(invest)])

I will get a result, but for the number 41, I get the growth rate between General Motors and General Electric, and for my question, I want to have the number 41 value be NA.

just like

id firm invest
1  A    2
2  A    1 
3  A    4
4  A    3
1  B    2
2  B    5
3  B    2
4  B    1

then

id firm invest growth rate
1  A    1         NA
2  A    2         1          
3  A    3        0.5
4  A    4        0.3333
1  B    5        NA
2  B    6        0.2
3  B    7        0.1666.
4  B    8        0.14

so what is the command for this situation? Many thanks.

Upvotes: 2

Views: 4847

Answers (5)

Sebastian
Sebastian

Reputation: 1369

A superior and fast solution to this problem is now available with the collapse R package and the generic function fgrowth and associated growth operator G. It also has methods for plm objects:

data("Grunfeld",package = "AER")
library("plm") 
gr <- subset(Grunfeld, firm %in% c("General Electric","General Motors"))
pgr <- pdata.frame(gr, index = c("firm","year"))

library(collapse)
# This computes the proper panel growth rate of all numeric variables
G(pgr)
head(G(pgr))
                              firm year  G1.invest   G1.value  G1.capital
General Motors-1935 General Motors 1935         NA         NA          NA
General Motors-1936 General Motors 1936  23.362720  51.427643 1778.571429
General Motors-1937 General Motors 1937   4.798367  15.560847  198.288973
General Motors-1938 General Motors 1938 -37.238188 -48.168774   33.333333
General Motors-1939 General Motors 1939  28.366317  54.473175   -2.772467
General Motors-1940 General Motors 1940  39.419589   7.667161    1.868240

# You could add those growth rates to the data.frame using
add_vars(pgr) <- G(pgr, keep.ids = FALSE)

# You can only compute the growth rate of invest and turn off the automatic renaming with
G(pgr, cols = "invest", stubs = FALSE)

                                  firm year     invest
General Motors-1935     General Motors 1935         NA
General Motors-1936     General Motors 1936  23.362720
General Motors-1937     General Motors 1937   4.798367
General Motors-1938     General Motors 1938 -37.238188
General Motors-1939     General Motors 1939  28.366317

# You could also compute the growth rate of the panel-series directly:
G(pgr$invest)
  General Motors-1935   General Motors-1936   General Motors-1937   General Motors-1938   General Motors-1939   General Motors-1940 
                   NA             23.362720              4.798367            -37.238188             28.366317             39.419589 
  General Motors-1941   General Motors-1942   General Motors-1943   General Motors-1944   General Motors-1945   General Motors-1946 
            11.014744            -12.500000             11.517857              9.587670              2.502283             22.612259 
  General Motors-1947   General Motors-1948   General Motors-1949   General Motors-1950   General Motors-1951   General Motors-1952 
           -17.323064             -6.978379              4.894180             15.816970             17.576606             17.899193 
  General Motors-1953   General Motors-1954 General Electric-1935 General Electric-1936 General Electric-1937 General Electric-1938 
            46.364452             13.975774                    NA             35.951662             71.555556            -42.227979 
General Electric-1939 General Electric-1940 General Electric-1941 General Electric-1942 General Electric-1943 General Electric-1944 
             7.847534             54.677755             51.881720            -18.672566            -33.297062             -7.340946 
General Electric-1945 General Electric-1946 General Electric-1947 General Electric-1948 General Electric-1949 General Electric-1950 
            64.788732             70.833333             -7.942464             -0.611413            -32.809296             -4.883011 
General Electric-1951 General Electric-1952 General Electric-1953 General Electric-1954 
            44.598930             16.346154             14.113160              5.626741 

fgrowth / G is fully C++ based, so this beats all other solutions in terms of speed and can also be applied to much larger panels:

library(microbenchmark)

microbenchmark(G(pgr))
Unit: microseconds
   expr    min     lq     mean median      uq     max neval
 G(pgr) 47.302 48.642 54.48262 49.533 50.6495 186.086   100

By the way: with flag / L / F and fdiff / D, collapse also implements similar solutions for lags, leads and lagged/leaded and iterated differences.

Upvotes: 3

Iman
Iman

Reputation: 2324

Using dplyr package:

Grunfeld %>% 
  select(firm,invest) %>%
  group_by(firm) %>%
  mutate(growth = c(NA,diff(invest))/lag(invest, 1))

Upvotes: 4

Richard Herron
Richard Herron

Reputation: 10092

I would use ave in base R and write my own function.

data("Grunfeld", package = "AER")
Grunfeld <- Grunfeld[order(Grunfeld$firm, Grunfeld$year), ]
myGR <- function(x, n=1) {
    c(rep(NA, n), diff(x, n) / head(x, -1*n))
}
Grunfeld$grInvest <- ave(Grunfeld$invest, Grunfeld$firm, FUN=myGR)   

Edit: This fails if you have missing years (i.e., this approach isn't aware of the year, only the relative position), but I usually fill these in with expand.grid.

fullPanel <- expand.grid(unique(Grunfeld$firm), min(Grunfeld$year):max(Grunfeld$year))
names(fullPanel) <- c("firm", "year")
GrunfeldAlt <- Grunfeld[-5, ]
GrunfeldAlt <- merge(GrunfeldAlt, fullPanel, all=TRUE)

Upvotes: 3

Jason
Jason

Reputation: 1569

EDIT: In the QuantMod package you can find the command PercChange. You can also use the slide command if you don't want a percent.

data(mtcars)

x<-split(mtcars,f=as.factor(mtcars$gear))

for(i in names(x)){
    x[[i]]<-PercChange(data=x[[i]],Var='mpg')
}

data<-unsplit(x,f=as.factor(mtcars$gear))

Upvotes: 0

GSee
GSee

Reputation: 49810

There are lots of functions out there to calculate returns: TTR::ROC, quantmod::dailyReturn, quantmod::Delt, etc., but I'll use yours.

myReturn <- function(x) c(NA, diff(x)/x[-length(x)])

There are at least a dozen ways to do this. Search for "split, apply, combine", "group by", "by", "tapply", "ave". Here are a couple ways.

data.table

library(data.table)
setDT(pgr) # convert to a data.table
pgr[, invest_growth:=myReturn(invest), by=firm] 
# if you don't want to create a column, pgr[, myReturn(invest), by=firm] will do.

split, lapply

pgr$invest_growth <-  unlist(lapply(split(pgr, pgr$firm), function(x) myReturn(x$invest)))

Upvotes: 0

Related Questions