Metadata-Version: 2.4
Name: wru
Version: 0.2.0
Summary: Who Are You? Bayesian Prediction of Racial Category Using Surname and Geolocation
License: MIT
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: pandas>=1.5
Requires-Dist: numpy>=1.20
Requires-Dist: requests>=2.28
Provides-Extra: names
Requires-Dist: pyreadr>=1.2; extra == "names"
Provides-Extra: fast
Requires-Dist: numba>=0.56; extra == "fast"
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: ipython; extra == "dev"
Requires-Dist: pyreadr>=1.2; extra == "dev"

# wru (Python)

Python implementation of **[wru](https://github.com/kosukeimai/wru)** (Who aRe yoU), the R package for Bayesian prediction of racial category using surname, first name, middle name, and geolocation.

Based on the methodology from Imai & Khanna (2016) and Imai, Khanna & McConnaughy (2022). Produces identical results to R wru v3.0.3 — validated on the exact 10-voter dataset from the R package README across surname-only, tract, and place geography levels (max |Δ| < 1e-6).

## Installation

```bash
pip install .
```

For first/middle name support (BIFSG), also install `pyreadr`:

```bash
pip install ".[names]"
```

For faster fBISG Gibbs sampling with numba:

```bash
pip install ".[fast]"
```

## Quick start

```python
import pandas as pd
import wru

voters = pd.DataFrame({
    "surname": ["Khanna", "Imai", "Rivera", "Johnson"],
    "state":   ["NJ",     "NJ",   "NY",     "NY"],
    "county":  ["021",    "021",  "061",    "061"],
    "tract":   ["004000", "004501", "004800", "014900"],
})

# Surname only
result = wru.predict_race(voters, surname_only=True)

# BISG with tract-level geography
result = wru.predict_race(voters, census_geo="tract")
```

Output columns `pred_whi`, `pred_bla`, `pred_his`, `pred_asi`, `pred_oth` contain posterior P(race | data) probabilities that sum to 1.

## Features

### Geography levels

Pass `census_geo` to condition on location. Supported levels: `"county"`, `"tract"`, `"block_group"`, `"block"`, `"place"`, `"zcta"`.

```python
result = wru.predict_race(voters, census_geo="tract")
result = wru.predict_race(voters, census_geo="place")
```

The voter file must contain a `state` column (2-letter abbreviation) plus the relevant geography columns (`county`, `tract`, `place`, `zcta`, etc.).

### BIFSG (first and middle names)

When first or middle name columns are available, BIFSG multiplies in additional name likelihoods:

```python
voters["first"] = ["Kabir", "Kosuke", "Carlos", "Frank"]
result = wru.predict_race(voters, census_geo="tract", first_name_col="first")
```

### Age and sex conditioning

Condition on age and/or sex using 2020 DHC P12 tables:

```python
voters["age"] = [29, 40, 33, 25]
voters["sex"] = [0, 0, 0, 0]  # 0=male, 1=female
result = wru.predict_race(voters, census_geo="county", age_col="age", sex_col="sex")
```

### Party conditioning

Multiply in P(party | race) priors:

```python
voters["PID"] = [0, 1, 2, 1]  # 0=other, 1=Dem, 2=Rep
result = wru.predict_race(voters, census_geo="tract", party_col="PID")
```

Note: R wru v3.0.3 accepts but silently ignores the `party` parameter. This Python version actually applies party conditioning.

### fBISG (measurement-error model)

The Gibbs sampler accounts for measurement error in Census counts:

```python
result = wru.predict_race(voters, census_geo="tract", method="fbisg", n_samples=1000, burnin=200)
```

### Census API key

For geographic conditioning, wru fetches data from the Census API. Requests work without a key (limited to 500/day). For heavier use, get a free key at https://api.census.gov/data/key_signup.html and set:

```bash
export CENSUS_API_KEY=your_key_here
```

Or pass it directly:

```python
result = wru.predict_race(voters, census_geo="tract", census_key="your_key")
```

Census data is cached locally in `~/.cache/wru/` after the first download.

## API reference

### `predict_race(voter_file, ...)`

Main entry point. Key parameters:

| Parameter | Default | Description |
|-----------|---------|-------------|
| `surname_col` | `"surname"` | Column with last names |
| `first_name_col` | `None` | Column with first names (enables BIFSG) |
| `middle_name_col` | `None` | Column with middle names |
| `census_geo` | `None` | Geography level for conditioning |
| `surname_only` | `False` | Skip geographic conditioning |
| `age_col` | `None` | Column with ages (integer) |
| `sex_col` | `None` | Column with sex (0=male, 1=female) |
| `party_col` | `None` | Column with party codes (0, 1, 2) |
| `method` | `"bisg"` | `"bisg"` or `"fbisg"` |
| `census_year` | `2020` | Census data year (2010 or 2020) |
| `use_wru_names` | `True` | Use wru's augmented name dictionaries |
| `cache` | `True` | Cache downloaded Census data locally |

### Helper functions

- `get_census_data(states, geo, year, ...)` — pre-download Census data for multiple states
- `get_surnames(year)` — load the Census surname list
- `get_name_dict(name_type)` — load wru name dictionaries (`"last"`, `"first"`, `"middle"`)
- `merge_names(voter_file, ...)` — merge name-based race likelihoods onto a voter file

## References

- Imai, K. and Khanna, K. (2016). "Improving Ecological Inference by Predicting Individual Ethnicity from Voter Registration Records." *Political Analysis*, 24(2), 263-272.
- Imai, K., Khanna, K. and McConnaughy, C.M. (2022). "Addressing Census Data Problems in Race Imputation via Fully Bayesian Improved Surname Geocoding and Name Supplements." *Working Paper*.
- R package: https://github.com/kosukeimai/wru

## License

MIT
