x <- 2:3
#---- Contributions for a geometric index ----
geometric_mean(x) - 1 # percent change in the Jevons index
geometric_contributions(x)
all.equal(geometric_mean(x) - 1, sum(geometric_contributions(x)))
# This works by first transmuting the weights in the geometric mean
# into weights for an arithmetic mean, then finding the contributions
# to the percent change
transmute_weights(0, 1)(x) * (x - 1)
# Not the only way to calculate contributions
transmute2 <- function(x) {
m <- geometric_mean(x)
(m - 1) / log(m) * log(x) / (x - 1) / length(x)
}
transmute2(x) * (x - 1) # not proportional to the method above
all.equal(sum(transmute2(x) * (x - 1)), geometric_mean(x) - 1)
# But these "transmuted" weights don't recover the geometric mean!
# Not a particularly good way to calculate contributions
isTRUE(all.equal(
arithmetic_mean(x, transmute2(x)),
geometric_mean(x)
))
# There are infinitely many ways to calculate contributions, but the
# weights from transmute_weights(0, 1)() are the *unique* weights that
# recover the geometric mean
perturb <- function(w, e) {
w + c(e, -e) / (x - 1)
}
perturb(transmute2(x), 0.1) * (x - 1)
all.equal(
sum(perturb(transmute2(x), 0.1) * (x - 1)),
geometric_mean(x) - 1
)
isTRUE(all.equal(
arithmetic_mean(x, perturb(transmute2(x), 0.1)),
geometric_mean(x)
))
#---- Contributions for a Fisher index ----
p1 <- price6[[2]]
p0 <- price6[[1]]
q1 <- quantity6[[2]]
q0 <- quantity6[[1]]
# Percent-change contributions for the Fisher index in section 6 of
# Reinsdorf et al. (2002)
(con <- fisher_contributions(
p1 / p0,
index_weights("Laspeyres")(p0, q0),
index_weights("Paasche")(p1, q1)
))
all.equal(sum(con), fisher_index(p1, p0, q1, q0) - 1)
# Not the only way
(con2 <- fisher_contributions2(
p1 / p0,
index_weights("Laspeyres")(p0, q0),
index_weights("Paasche")(p1, q1)
))
all.equal(sum(con2), fisher_index(p1, p0, q1, q0) - 1)
# The same as the van IJzeren decomposition in section 4.2.2 of
# Balk (2008)
Qf <- quantity_index(fisher_index)(q1, q0, p1, p0)
Ql <- quantity_index(laspeyres_index)(q1, q0, p0)
wl <- scale_weights(index_weights("Laspeyres")(p0, q0))
wp <- scale_weights(index_weights("HybridPaasche")(p0, q1))
(Qf / (Qf + Ql) * wl + Ql / (Qf + Ql) * wp) * (p1 / p0 - 1)
# Similar to the method in section 2 of Reinsdorf et al. (2002),
# although those contributions aren't based on weights that sum to 1
Pf <- fisher_index(p1, p0, q1, q0)
Pl <- laspeyres_index(p1, p0, q0)
(1 / (1 + Pf) * wl + Pl / (1 + Pf) * wp) * (p1 / p0 - 1)
# Also similar to the decomposition by Hallerbach (2005), noting that
# the Euler weights are close to unity
Pp <- paasche_index(p1, p0, q1)
(0.5 * sqrt(Pp / Pl) * wl + 0.5 * sqrt(Pl / Pp) * wp) * (p1 / p0 - 1)
#---- Contributions for other types of indexes ----
# A function to get contributions for any superlative quadratic mean of
# order 'r' index
superlative_contributions <- function(r) {
nested_contributions(0, c(r / 2, -r / 2))
}
# Can be used to decompose the implict Walsh index
superlative_contributions(1)(
p1 / p0,
index_weights("Laspeyres")(p0, q0),
index_weights("Paasche")(p1, q1)
)
# Works for other types of indexes, like the harmonic
# Laspeyres Paasche index
hlp_contributions <- nested_contributions(-1, c(1, -1))
hlp_contributions(
p1 / p0,
index_weights("Laspeyres")(p0, q0),
index_weights("Paasche")(p1, q1)
)
# Or the AG mean index (tau = 0.25)
agmean_contributions <- nested_contributions(1, c(0, 1), c(0.25, 0.75))
agmean_contributions(
p1 / p0,
index_weights("Laspeyres")(p0, q0),
index_weights("Laspeyres")(p0, q0)
)
# Or the Balk-Walsh index
bw_contributions <- nested_contributions(0, c(0.5, -0.5))
bw_contributions(p1 / p0)
Run the code above in your browser using DataLab