This vignette sets out how the results of the package are checked: against version 0.5.0, against the published index numbers of the Consumer Price Index Manual, against the identities the formulas must satisfy, and it ends with timings against version 0.5.0.
2 Against version 0.5.0
The example of version 0.5.0, run with a seed, was saved before the rewrite (dev/legacy), and the test test-legacy.R compares the new results with it. With logbase = 10 (the default of 0.5.0) and with logbase = 2 or \(e\), and for the Hancock method, DMAI agrees to \(10^{-10}\). The one change is the default logarithm: 0.5.0 used base 10, so its default DMAI was \(1/\log 10 \approx 0.434\) times the growth rate; 1.0.0 uses the natural logarithm, and the ratio of the two is \(\log 10 \approx 2.303\):
Date natural base10 ratio
<Date> <num> <num> <num>
1: 2005-01-01 NA NA NA
2: 2005-02-01 0.8504011 0.3693245 2.302585
3: 2005-03-01 1.7328708 0.7525762 2.302585
4: 2005-04-01 -0.2494176 -0.1083207 2.302585
5: 2005-05-01 0.3359143 0.1458857 2.302585
6: 2005-06-01 0.8085785 0.3511612 2.302585
3 Against published index numbers
A Divisia quantity index is the index of Tornqvist with the user costs in the place of prices; the formula is symmetric in prices and quantities, so with the prices as x and the quantities as user_cost the package computes a Tornqvist price index. The Consumer Price Index Manual (ILO et al. 2004, Chapter 19) gives the chained Laspeyres, Paasche, Fisher and Tornqvist price indexes of an artificial data set, shipped as cpi_ch19:
The Manual prints (Tables 19.5 and 19.11): Laspeyres 1.4200, 1.3646, 1.3351, 1.3306; Paasche 1.3823, 1.2740, 1.2060, 1.1234; Fisher 1.4011, 1.3185, 1.2689, 1.2226; Tornqvist 1.4052, 1.3112, 1.2624, 1.2224. Every value agrees to the printed digits except the Paasche index of period 2, \(14.10/10.20 = 1.38235\), printed as 1.3823. Each value is a row of inst/extdata/reference.csv, checked at every R CMD check:
the Divisia, Fisher, Hancock, simple-sum and currency equivalent indexes equal their formulas computed by hand on a small example;
price times quantity is the expenditure (factor reversal), and the implicit price index of the Fisher quantity index is the Fisher price index of the user costs;
the shares sum to one at every date, and do not change when the rates are given as decimals instead of percent;
the Divisia mean of dmai_moments() is the Divisia growth, and the variance is never negative;
the order of the rows and the names of the columns do not change the result.
For example, factor reversal:
f <-dmai(.data = money_sim , method ="Fisher" , logbase =NULL , date ="Date" , x =NULL , r =NULL , user_cost =NULL , benchmark ="rb" , percent =TRUE , base =100 , as_dt =FALSE )max(abs(f$price$price * f$index$value - f$price$expenditure))
[1] 4.547474e-13
5 Speed
Version 0.5.0 reshaped the data to a long table with tidyr and computed with grouped dplyr operations; version 1.0.0 works on the matrix of quantities. The timings below were taken by tools/bench.R on simulated data (median of 20 runs, milliseconds) and are stored with the package:
b <- data.table::fread(system.file("extdata", "bench.csv", package ="dmai"))w <- data.table::dcast(data = b, formula = case ~ version, value.var ="median_ms")v <-sort(unique(b$version))w[, speedup :=round(x =get(v[1]) /get(v[2]), digits =1)]w