Skip to content

Commit 247638e

Browse files
Drop dependency on assertthat and refactor calcTheil
1 parent 691bcdf commit 247638e

File tree

4 files changed

+48
-85
lines changed

4 files changed

+48
-85
lines changed

DESCRIPTION

-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ Depends:
4646
R (>= 2.10.0)
4747
Imports:
4848
assertr,
49-
assertthat,
5049
broom,
5150
car,
5251
countrycode,

NAMESPACE

-1
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,6 @@ importFrom(stats,na.exclude)
199199
importFrom(stats,na.omit)
200200
importFrom(stats,na.pass)
201201
importFrom(stats,nls)
202-
importFrom(stats,qnorm)
203202
importFrom(stats,sd)
204203
importFrom(stats,weighted.mean)
205204
importFrom(tibble,as_tibble)

R/calcTheil.R

+42-74
Original file line numberDiff line numberDiff line change
@@ -1,101 +1,69 @@
11
#' Calculate regional Theil-T index
22
#'
3-
4-
#' To calculate the regional Theil-T index (= correction to welfare function for
5-
#' a lognormal income distribution) we do the following:
6-
#' (1) convert country-level Gini coefficients to Theil (2) calculate contribution
7-
#' to Theil-T index that includes both between-countries and within-country inequality
8-
#' (see e.g. https://en.wikipedia.org/wiki/Theil_index). The latter can then be
9-
#' aggregated with calcOutput().
3+
#' To calculate the regional Theil-T index (= correction to welfare function for a lognormal income distribution) we do
4+
#' the following: (1) convert country-level Gini coefficients to Theil (2) calculate contribution to Theil-T index that
5+
#' includes both between-countries and within-country inequality (see e.g. https://en.wikipedia.org/wiki/Theil_index).
6+
#' The latter can then be aggregated with calcOutput().
107
#'
118
#' NB 1: the aggregation depends on the region mapping. It is implemented such
129
#' that the regionmapping specified in getConfig()$regionmapping is used.
1310
#'
1411
#' NB 2: the result of calcOutput('Theil', aggregate = FALSE), is NOT the country
1512
#' Theil-T, but the unweighted contribution from a given country to the regional value.
1613
#'
17-
#' @return magpie objects of unweighted contribution to Theil,
18-
#' weights (= country shares of regional GDP), docstring
14+
#' @return magpie objects of unweighted contribution to Theil, weights (= country shares of regional GDP)
1915
#' @author Bjoern Soergel
2016
#' @seealso \code{\link{calcOutput}} \code{\link{convertGini},\link{readGini}}
2117
#' @examples
2218
#' \dontrun{
23-
#' a <- calcOutput("Theil")
19+
#' calcOutput("Theil")
2420
#' }
2521
#'
26-
#' @importFrom stats qnorm
27-
2822
calcTheil <- function() {
29-
30-
## helper functions.
31-
TheilT.from.sigma <- function(sigma) {
32-
# Theil T coefficient for lognormal distribution
33-
TheilT <- sigma^2 / 2.
34-
return(TheilT)
35-
}
36-
37-
sigma.from.Gini <- function(G) {
38-
# assuming lognormal distribution: convert Gini to sigmas
39-
sigma <- sqrt(2) * qnorm((G + 1) / 2)
40-
return(sigma)
41-
}
42-
43-
# Gini and Theil
23+
# Read Gini
4424
Gini <- readSource("Gini")
45-
years <- getYears(Gini)
46-
TheilT <- TheilT.from.sigma(sigma.from.Gini(Gini))
4725

48-
# population (in 1e6)
49-
pop <- calcOutput(type = "Population", aggregate = FALSE)
50-
sspnames <- c(paste0("SSP", 1:5), "SDP", "SSP2EU")
51-
pop <- pop[, years, paste0("pop_", sspnames)]
52-
getNames(pop) <- sspnames
53-
getSets(pop) <- c("iso3c", "year", "scenario")
26+
# Convert Gini to sigmas assuming lognormal distribution
27+
sigma <- sqrt(2) * stats::qnorm((Gini + 1) / 2)
28+
# Theil T coefficient for lognormal distribution
29+
TheilT <- sigma^2 / 2
5430

55-
# GDP (in million $ PPP 2005)
56-
GDPppp <- calcOutput(type = "GDP", aggregate = FALSE)
57-
GDPnames <- paste0("gdp_", sspnames)
58-
GDPppp <- GDPppp[, years, GDPnames]
59-
getNames(GDPppp) <- sspnames
60-
getSets(GDPppp) <- c("iso3c", "year", "scenario")
31+
# We need the GDP and GDP per capita scenarios, for the scenarios and years of Gini.
32+
# We set extension2150 = "constant" because the Gini coefficients are also extended in the same way.
33+
# As a regionmapping we use the one set in the config (which is the default behavior). We call it explicitly as it is
34+
# used in the calculations of the Theil contribution and weights.
35+
s <- getNames(Gini)
36+
y <- getYears(Gini)
37+
gdp <- calcOutput("GDP", naming = "scenario", extension2150 = "constant", years = y, aggregate = FALSE)[, , s]
38+
gdpReg <- calcOutput("GDP", naming = "scenario", extension2150 = "constant", years = y)[, , s]
39+
gdppc <- calcOutput("GDPpc", naming = "scenario", extension2150 = "constant", years = y, aggregate = FALSE)[, , s]
40+
gdppcReg <- calcOutput("GDPpc", naming = "scenario", extension2150 = "constant", years = y)[, , s]
6141

62-
# allocate empty objects for storing Theil contribution and weights
63-
contribTheilT <- pop
42+
# Allocate empty objects for storing Theil contribution and weights
43+
contribTheilT <- TheilT
6444
contribTheilT[, , ] <- NA
65-
s_i <- pop
66-
s_i[, , ] <- NA
67-
68-
# contribution to Theil index depends on region mapping. We always use the one specified in getConfig().
69-
regionmapping <- read.csv(
70-
toolGetMapping(
71-
type = "regional", name = getConfig()$regionmapping,
72-
returnPathOnly = TRUE, where = "mappingfolder"
73-
),
74-
sep = ";", colClasses = "character"
75-
)
45+
weight <- TheilT
46+
weight[, , ] <- NA
7647

77-
# GDP per capita
78-
xbar_i <- GDPppp / pop
79-
for (rr in unique(regionmapping$RegionCode)) {
48+
# Compute Theil contribution and weights
49+
regionmapping <- toolGetMapping(getConfig("regionmapping"), type = "regional", where = "mappingfolder")
50+
for (rr in getRegions(gdppcReg)) {
8051
rrCountries <- regionmapping$CountryCode[regionmapping$RegionCode == rr]
81-
# regional GDP per capita
82-
GDPppp_rr <- dimSums(GDPppp[rrCountries, , ], dim = 1)
83-
Ntot_rr <- dimSums(pop[rrCountries, , ], dim = 1)
84-
xbar_rr <- GDPppp_rr / Ntot_rr
85-
# contribution to Theil index (unweighted)
86-
contribTheilT[rrCountries, , ] <- TheilT[rrCountries, , ] + log(xbar_i[rrCountries, , ] / xbar_rr)
87-
# weights = income share of country i:
88-
# s_i = N_i/N * xbar_i/xbar = GDP_i/GDP_rr # nolint
89-
s_i[rrCountries, , ] <- GDPppp[rrCountries, , ] / GDPppp_rr
90-
# sanity check: ensure that weights for a region sum to one (within floating point precision)
91-
assertthat::assert_that(max(abs(dimSums(s_i[rrCountries, , ], dim = 1) - 1)) < 1e-10)
52+
# Contribution to Theil index (unweighted)
53+
contribTheilT[rrCountries, , ] <- TheilT[rrCountries, , ] + log(gdppc[rrCountries, , ] / gdppcReg[rr, , ])
54+
# Weights = country shares of regional GDP
55+
weight[rrCountries, , ] <- gdp[rrCountries, , ] / gdpReg[rr, , ]
56+
# Sanity check: ensure that weights for a region sum to one (within floating point precision)
57+
stopifnot(max(abs(dimSums(weight[rrCountries, , ], dim = 1) - 1)) < 1e-10)
9258
}
9359

94-
# for easier REMIND integration use same names as GDP scenarios for Theil
95-
# change this if we later want to test effect of per capita income growth vs. inequality
96-
getNames(contribTheilT) <- GDPnames
97-
getNames(s_i) <- GDPnames
60+
# For easier REMIND integration use same names as GDP scenarios for Theil
61+
# Change this if we later want to test effect of per capita income growth vs. inequality
62+
getNames(contribTheilT) <- paste0("gdp_", getNames(contribTheilT))
63+
getNames(weight) <- paste0("gdp_", getNames(weight))
9864

99-
return(list(x = contribTheilT, weight = s_i, unit = "-",
100-
description = "aggregated: Theil-T index, not-aggregated: unweighted contribution to Theil-T"))
65+
list(x = contribTheilT,
66+
weight = weight,
67+
unit = "-",
68+
description = "Aggregated: Theil-T index. Not-aggregated: unweighted contribution to Theil-T")
10169
}

man/calcTheil.Rd

+6-9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)