Skip to main content

PyIndexNum

PyPI version Python 3.10+ License: MIT Documentation Status

A high-performance Python library for calculating economic index numbers using Polars. Designed for statisticians and economists working with price and quantity indices.

Features

  • High Performance: Built on Polars for efficient data processing of large datasets
  • Comprehensive Index Methods: Support for bilateral and multilateral price/quantity indices
  • Data Preparation Tools: Built-in utilities for data standardization and temporal aggregation
  • Panel Data Handling: Robust methods for dealing with unbalanced panels through removal or imputation
  • Extension Methods: Support for index splicing and rolling window calculations
  • Type Safety: Full type annotations for better IDE support and code reliability

Installation

Using pip

pip install pyindexnum

Using uv

uv add pyindexnum

From source

git clone https://github.com/paluigi/PyIndexNum.git
cd PyIndexNum
uv sync

Quick Start

Here's the typical workflow for calculating economic indices:

import polars as pl
import pyindexnum as pin

# Load your price data
df = pl.read_csv("price_data.csv")

# 1. Standardize column names
df_std = pin.standardize_columns(df, date_col="date", price_col="price", id_col="product_id", quantity_col="quantity")

# 2. Aggregate to desired time frequency
df_agg = pin.aggregate_time(df_std, freq="1mo", agg_type="arithmetic")

# 3. Handle unbalanced panels (optional)
df_balanced = pin.remove_unbalanced(df_agg)
# or
df_imputed = pin.carry_forward_imputation(df_agg, ["aggregated_price", "aggregated_quantity"])

# 4. Calculate bilateral indices (two periods)
laspeyres_idx = pin.laspeyres(df_balanced)
fisher_idx = pin.fisher(df_balanced)

# 5. Calculate multilateral indices (multiple periods)
# Split data into two overlapping rolling windows
periods = sorted(df_agg["period"].unique())
window1 = df_agg.filter(pl.col("period").is_in(periods[:-1]))
window2 = df_agg.filter(pl.col("period").is_in(periods[1:]))

geks_fisher_idx1 = pin.geks_fisher(window1)
geks_fisher_idx2 = pin.geks_fisher(window2)

# 6. Apply extension methods (optional)
extended_idx = pin.movement_splice(geks_fisher_idx1, geks_fisher_idx2)

Supported Index Methods

Bilateral Indices (Two-Period Comparisons)

Index Formula Use Case
Jevons Geometric mean of price relatives Unweighted geometric average
Carli Arithmetic mean of price relatives Unweighted arithmetic average
Dutot Ratio of arithmetic means of prices Simple price average comparison
Laspeyres Weighted by base period quantities Fixed basket approach
Paasche Weighted by current period quantities Current basket approach
Fisher Geometric mean of Laspeyres and Paasche Ideal index (time/quantity reversal)
Törnqvist Weighted geometric mean with average expenditure shares Symmetric treatment
Walsh Geometric mean of quantities as fixed basket Alternative symmetric approach

Multilateral Indices (Multi-Period Comparisons)

Index Method Description
GEKS-Fisher Chained Fisher indices Most widely used multilateral method
GEKS-Törnqvist Chained Törnqvist indices Alternative chaining approach
GEKS-Jevons Unweighted geometric mean of price relatives Transitive multilateral index (no quantity)
Geary-Khamis System of equations Global approach
Time Product Dummy Regression-based WLS with expenditure shares or unweighted OLS

Extension Methods

  • Movement Splice: Chain indices using movement ratios
  • Window Splice: Moving window chaining
  • Half Splice: Half-year overlapping windows
  • Mean Splice: Average of overlapping windows
  • Fixed Base Rolling Window: Rolling window with fixed base

Data Requirements

Your data should contain:

  • Date column: Date or datetime values
  • Price column: Numeric price observations
  • Product ID column: Unique identifier for each product/variety
  • Quantity column: Numeric quantities (required for weighted indices, optional for unweighted methods like GEKS-Jevons)

Example data structure:

┌────────────┬────────────┬───────┬──────────┐
│ date       ┆ product_id ┆ price ┆ quantity │
│ ---        ┆ ---        ┆ ---   ┆ ---      │
│ date       ┆ str        ┆ f64   ┆ f64      │
╞════════════╪════════════╪═══════╪══════════╡
│ 2023-01-01 ┆ A          ┆ 100.0 ┆ 10.0     │
│ 2023-01-01 ┆ B          ┆ 200.0 ┆ 5.0      │
│ 2023-02-01 ┆ A          ┆ 105.0 ┆ 12.0     │
│ 2023-02-01 ┆ B          ┆ 210.0 ┆ 4.5      │
└────────────┴────────────┴────────────┴──────────┘

API Overview

Data Preparation

# Standardize column names and types
df_std = pin.standardize_columns(df, date_col="date", price_col="price", id_col="id")

# Aggregate time series data
df_agg = pin.aggregate_time(df_std, freq="1mo", agg_type="weighted_arithmetic")

# Handle unbalanced panels
df_balanced = pin.remove_unbalanced(df_agg)
df_imputed = pin.carry_forward_imputation(df_agg, ["aggregated_price", "aggregated_quantity"])

Index Calculation

# Bilateral indices
jevons = pin.jevons(df)
laspeyres = pin.laspeyres(df)
fisher = pin.fisher(df)

# Multilateral indices
geks = pin.geks_fisher(df)
gk = pin.geary_khamis(df)

# Unweighted multilateral index (no quantity required)
geks_j = pin.geks_jevons(df)

Extensions

# Splicing methods
movement_spliced = pin.movement_splice(multilateral_index1, multilateral_index2)
window_spliced = pin.window_splice(multilateral_index1, multilateral_index2)

Documentation

Full documentation is available at https://pyindexnum.readthedocs.io/

Contributing

PyIndexNum is an open-source project and welcomes contributions! See our contributing guide for details.

Development Setup

# Clone and setup
git clone https://github.com/paluigi/PyIndexNum.git
cd PyIndexNum
uv sync --dev

# Run tests
uv run pytest

# Build documentation
cd docs && make html

Areas for Contribution

  • New index methods and formulations
  • Performance optimizations
  • Additional data validation
  • Enhanced documentation and examples
  • Bug fixes and improvements

Citation

If you use PyIndexNum in your research, please cite:

@software{pyindexnum,
  title = {PyIndexNum: A Python Library for Economic Index Numbers},
  author = {Palumbo, Luigi, and Yu, Mengting},
  url = {https://github.com/paluigi/PyIndexNum},
  version = {0.3.0},
}

License

PyIndexNum is licensed under the MIT License. See LICENSE for details.

Related Projects

  • Polars: The high-performance DataFrame library that powers PyIndexNum

Built with ❤️ for the economic statistics community

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyindexnum-0.3.0.tar.gz (143.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyindexnum-0.3.0-py3-none-any.whl (20.6 kB view details)

Uploaded Python 3

File details

Details for the file pyindexnum-0.3.0.tar.gz.

File metadata

  • Download URL: pyindexnum-0.3.0.tar.gz
  • Upload date:
  • Size: 143.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for pyindexnum-0.3.0.tar.gz
Algorithm Hash digest
SHA256 a10b5255df66a9b3a702f34bed3c2887b9f64ffcc8d5f79a74a6f67e1dc10449
MD5 8d646e8744cd9a165f74e4fa92de6b41
BLAKE2b-256 fd6728b730623be5ccc016d76a0fdfe1b9b862b7027463243382c730b5f05623

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyindexnum-0.3.0.tar.gz:

Publisher: python-publish.yml on paluigi/PyIndexNum

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyindexnum-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: pyindexnum-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 20.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for pyindexnum-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f384a326051c10578033e33dffd27097cf7eda8f8e8b8e96922a65b45047682e
MD5 1352bc6526c15e363d44321cfde4fd93
BLAKE2b-256 040ed6025c195723cbcfea2b97d11381f1d6d55dcdb10c5c029cac9f079be0e3

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyindexnum-0.3.0-py3-none-any.whl:

Publisher: python-publish.yml on paluigi/PyIndexNum

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 files

0.2.0

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page