--- title: "Getting started with piar" vignette: > %\VignetteIndexEntry{Getting started with piar} %\VignetteEngine{litedown::vignette} %\VignetteEncoding{UTF-8} --- ```{r} #| echo: false litedown::reactor(print = NA) ``` Most price indexes are made with a two-step procedure, where period-over-period *elementary indexes* are calculated for a collection of *elementary aggregates* at each point in time, and then aggregated according to a *price index aggregation structure*. These indexes can then be chained together to form a time series that gives the evolution of prices with respect to a fixed base period. This package contains a collection of functions that revolve around this work flow, making it easy to build standard price indexes in **R**. The purpose of this vignette is to give an introductory example for how to use the core functionality in this package to make a standard price index. Subsequent vignettes go into more details on advanced topics, often referencing the example in this vignette. ## Industry-based index In this vignette we'll be calculating an industry-based producer price index where a fixed set of businesses each provide prices for a collection of products over time. The products reported by a businesses can change over time, but the set of businesses is fixed for the duration of the sample. Each businesses has a weight that is established when the sample is drawn and represents a particular segment of the economy. The usual approach for calculating an industry-based index starts by computing an elementary index for each business as an equally-weighted geometric mean of price relatives (i.e., a Jevons index). From there, index values for different segments of the economy are calculated as an arithmetic mean of the elementary indexes using the businesses-level weights (either a Young or Lowe index, depending how the weights are constructed; see `vignette("adjust-weights")`). The `ms_prices` dataset has price data for five businesses over four quarters, and the `ms_weights` dataset has the weight data. Note that these data have fairly realistic patterns of missing data and are emblematic of the kinds of survey data used to make price indexes. ```{r} library(piar) head(ms_prices) ms_weights ``` The `elementary_index()` function makes, well, elementary indexes, using information on price relatives, elementary aggregates (businesses), and time periods (quarters). By default it makes a Jevons index, but any bilateral generalized-mean index is possible (see `vignette("index-number-formulas")` for more details). The only wrinkle is that price data here are in levels, and not relatives, but the `price_relative()` function can make the necessary conversion. ```{r} elementals <- ms_prices |> transform( relative = price_relative(price, period = period, product = product) ) |> elementary_index(relative ~ period + business, na.rm = TRUE) elementals ``` As with most functions in **R**, missing values are contagious by default. Setting `na.rm = TRUE` in `elementary_index()` means that missing price relatives are ignored, which is equivalent to imputing these missing relatives with the value of the elementary index for the respective businesses (i.e., overall-mean imputation). Other types of imputation are covered in `vignette("imputation")`. The `elementary_index()` function returns a special index object, and there are a number of methods for working with these objects. For example, the resulting indexes to be extracted like a matrix (even though it's not a matrix).[^1] [^1]: Note that there are only indexes for four businesses, not five, because the fifth business never reports any prices. An elementary index can be made for this business by passing a factor with a level for all five businesses to `elementary_index()`. ```{r} elementals[, "202004"] elementals[c("B1", "B3"), ] ``` With the elementary indexes out of the way, it's time to make a price-index aggregation structure that maps each business to its position in the aggregation hierarchy. The only hiccup is unpacking the digit-wise classification for each businesses that defines the hierarchy. That's the job of the `expand_classification()` function. ```{r} ms_weights[c("level1", "level2")] <- expand_classification(ms_weights$classification) pias <- ms_weights[c("level1", "level2", "business", "weight")] |> as_aggregation_structure() ``` It is now simple to aggregate the elementary indexes according to this aggregation structure with the `aggregate()` function. As with the elementary indexes, missing values are ignored by setting `na.rm = TRUE`, which is equivalent to (recursively) imputing a missing value for a point in the aggregation structure by that of its parent. Note that, unlike the elementary indexes, missing values are filled in to ensure the index can be chained over time. ```{r} index <- aggregate(elementals, pias, na.rm = TRUE) index ``` ## Chaining The `elementary_index()` function makes period-over-period elementary indexes by default, which are then aggregated to make a period-over-period index. Chaining an index is the process of taking the cumulative product of each of these period-over-period indexes to make a time series that compares prices to a fixed base period. The `chain()` function can be used to chain the values in an index object. ```{r} chained_index <- chain(index) chained_index ``` This gives almost the same result as directly manipulating the index as a matrix, except that the former returns an index object (not a matrix). Chained indexes often need be to rebased, and this can be done with the `rebase()` function. For example, rebasing the index so that 202004 is the base period just requires dividing the chained index by the slice for 202004. ```{r} rebase(chained_index, base = chained_index[, "202004"]) ``` ## Working with indexes Once an index has been calculated, it usually needs to be turned into a table of index values. This can be done by either coercing an index into a matrix ```{r} as.matrix(chained_index) ``` or a data frame ```{r} as.data.frame(chained_index) ``` It is also sometimes useful to get the price-updated weights used to aggregate the index; these can be calculated by first updating the aggregation structure with the aggregated index, then made into a table. ```{r} update(pias, index) |> as.data.frame() ```