> ## Documentation Index
> Fetch the complete documentation index at: https://docs.effectiveai.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Prepare a book for comparison

> Load reported risk facts, preserve your own analysis dimensions, and check the population before comparing rating programs.

Prepare one book for every program in a comparison. Keep reported facts, carrier mappings, and analysis assumptions identifiable.

[Install Relativities and download the synthetic examples](/relativities/setup) before running this page.

```python theme={null}
from relativities import Book, ppa

book = Book.read_csv("relativities-examples/ppa/book", schema=ppa.SCHEMA)
book
# Book(6 households, 6 submissions, 7 drivers, 9 vehicles)
book.submissions[["submission_id", "household_id", "effective_date"]].head(2)
#   submission_id household_id effective_date
# 0            S1           H1     2026-10-01
# 1            S2           H2     2026-10-01
```

## Choose the population and unit of analysis

Use a market basket to study selected risk profiles, or a portfolio extract to study your observed business mix.
State the selection date, population, exclusions, and any weights in the exhibit.
Interpret a market basket's findings for the profiles and weights you selected.

Each `submission_id` identifies one request to price. A household can have several submissions, such as quotes at different effective dates.
Choose the appropriate unit before aggregating premiums: submission, vehicle, coverage, or another outcome the rater exposes.

## Put reported facts in the shared tables

The required tables are `households`, `submissions`, `drivers`, and `vehicles`.
Add coverage selections and incidents when the programs require them. The [PPA book schema](/relativities/reference/book-schema) gives their keys and columns.

| Source fact | Book location | Program responsibility |
| - | - | - |
| Birth date and effective date | `drivers`, `submissions` | Derive age under the carrier's rule |
| Date first licensed | `drivers` | Derive years licensed |
| Annual mileage | `vehicles` | Map mileage to the carrier's input |
| Coverage selection and deductible | `vehicle_coverages` | Apply a supported selection or raise a mapping error |
| Carrier vehicle symbol or territory assignment | A documented program input or mapping table | Preserve its source, version, and assignment assumptions |

Keep unknown facts blank. Add deliberate assumptions as [scenarios or draws](/relativities/explanation/books-and-studies), or in a documented program `prepare` function.
Treat unsupported coverage selections as exceptions to resolve or disclose in the comparison.

## Keep your own dimensions

Add columns for the cuts your study needs. This example adds a vehicle-count segment to each submission:

```python theme={null}
submissions = book.submissions
counts = book.vehicles.groupby("submission_id").size()
submissions["vehicle_segment"] = submissions["submission_id"].map(counts).map(
    lambda count: "multi_vehicle" if count > 1 else "single_vehicle"
)
prepared = book.with_tables(submissions=submissions)
prepared.submissions[["submission_id", "vehicle_segment"]]
#   submission_id vehicle_segment
# 0            S1  single_vehicle
# 1            S2   multi_vehicle
# 2            S3  single_vehicle
# 3            S4  single_vehicle
# 4            S5  single_vehicle
# 5            S6   multi_vehicle
```

Extra columns survive book operations. Add your own tables with `with_tables`, keyed by `submission_id` and any entity keys they need.
Keep broker, distribution channel, geography, or study weights at the level where they are defined.
Join those dimensions to rating results by their keys for analysis in pandas.

## Check completeness before rating

Count submissions and missing inputs before choosing assumptions:

```python theme={null}
book.drivers.groupby("submission_id")["first_licensed_date"].apply(lambda dates: dates.isna().sum())
# submission_id
# S1    0
# S2    0
# S3    0
# S4    0
# S5    1
# S6    0
# Name: first_licensed_date, dtype: int64
```

The book validates its schema and links when constructed. Each program's required inputs still need review against its `rater.inputs` table, its schema and its `prepare` function.
S5's missing date causes a mapping failure for the example carrier B; carrier A derives age from the reported birth date.

`Book.read_csv` preserves IDs and coverage codes as text. When importing other code columns with pandas, specify their text dtype to preserve leading zeros.
Verify vehicle symbols, territory codes, dates, units, and entity assignments before using them in a rater.

## Save the analysis inputs

```python theme={null}
prepared.to_csv("study-book")
reloaded = Book.read_csv("study-book", schema=ppa.SCHEMA)
reloaded.submissions["vehicle_segment"].tolist()
# ['single_vehicle', 'multi_vehicle', 'single_vehicle', 'single_vehicle', 'single_vehicle', 'multi_vehicle']
```

Retain this book with your program bundle IDs, assumptions, analysis code, and comparison basis.
`book.source` records the source location, and `book.hash` identifies the table contents.
A changed book has `source=None`; retain your original source and transformation steps with the study.
Next, [validate the programs](/relativities/how-to/validate-a-program) and [compare carriers](/relativities/how-to/compare-carriers) with rating exceptions visible.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.