Reputation: 39
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
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
Reputation: 2324
Using dplyr
package:
Grunfeld %>%
select(firm,invest) %>%
group_by(firm) %>%
mutate(growth = c(NA,diff(invest))/lag(invest, 1))
Upvotes: 4
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
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
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.
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.
pgr$invest_growth <- unlist(lapply(split(pgr, pgr$firm), function(x) myReturn(x$invest)))
Upvotes: 0