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

# Create a book

> Build a book of policies from pandas tables or CSV files, check it against the personal auto schema, and save it.

Build a book from pandas tables, and check it against the line's schema:

```python theme={null}
import pandas as pd

from relativities import Book, Program, ppa

book = Book(
    {
        "submissions": pd.DataFrame(
            {"submission_id": ["Q1"], "policy_id": ["P1"], "effective_date": ["2026-11-01"], "term_months": [6]}
        ),
        "drivers": pd.DataFrame(
            {"submission_id": ["Q1"], "driver_id": ["D1"], "birth_date": ["1990-04-02"], "first_licensed_date": ["2006-05-10"]}
        ),
        "vehicles": pd.DataFrame(
            {
                "submission_id": ["Q1"],
                "vehicle_id": ["V1"],
                "model_year": [2021],
                "make": ["Toyota"],
                "model": ["Camry"],
                "garaging_postal_code": ["94110"],
                "annual_mileage": [9_000],
            }
        ),
        "coverages": pd.DataFrame(
            {
                "submission_id": ["Q1", "Q1"],
                "vehicle_id": ["V1", "V1"],
                "coverage_id": ["bodily_injury", "property_damage"],
                "limit_per_person": [50_000, None],
                "limit_per_accident": [100_000, None],
                "limit": [None, 50_000],
            }
        ),
    },
    schema=ppa.SCHEMA,
)
book  # Book(1 policy, 1 submission, 1 driver, 1 vehicle)
```

Each row of `submissions` is one request to price. `drivers`, `vehicles` and `coverages` link to it
by `submission_id`. The book adds the `policies` table from each `policy_id`.

```mermaid theme={null}
flowchart LR
  submissions["submissions"] --> drivers["drivers"]
  submissions --> vehicles["vehicles"]
  vehicles --> coverages["coverages"]
  drivers --> incidents["incidents"]
  submissions --> other["other_policies"]
```

## Put facts in the core columns

* Put each reported fact in its core column, such as `birth_date`. The [PPA book schema](/relativities/reference/book-schema) lists each column.
* Leave an unknown fact blank. Each program sets its own default for a blank.
* Keep values that a carrier derives, such as an age or a territory, out of the book. A program's `prepare` derives them.

`Book` checks every table, key and type when you build it, and raises
[`BookError`](/relativities/reference/relativities#bookerror) with each problem at once.

## Read a book from CSV files

Write one CSV file per table in a folder, such as `vehicles.csv`. Read the folder with the schema:

```python theme={null}
book.to_csv("my-book")
Book.read_csv("my-book", schema=ppa.SCHEMA)  # Book(1 policy, 1 submission, 1 driver, 1 vehicle)
```

`read_csv` reads IDs and codes as text exactly as spelled, so a postal code keeps its leading zero.

## Start from the example book

The example program carries a book of 100,000 synthetic California policies. The other guides use
it as the running book:

```python theme={null}
program = Program.load("effective://example-ca-ppa")
book = program.example_book
book  # Book(100000 policies, 100000 submissions, 193158 drivers, 185985 vehicles)
```

[Load a program](/relativities/how-to/load-a-program) describes the library and its API key.

## Select policies

Select whole policies, with each of their rows:

```python theme={null}
first = book.select(policies=book.policies["policy_id"].head(3))
first.vehicles[["submission_id", "vehicle_id", "make", "model", "annual_mileage"]]
#   submission_id vehicle_id       make       model  annual_mileage
# 0       S000001         V1  Chevrolet    Colorado            6000
# 1       S000001         V2       Jeep    Wrangler            7500
# 2       S000002         V1       Ford    Explorer           10400
# 3       S000002         V2        Kia   Telluride           15000
# 4       S000003         V1      Dodge  Challenger           15000
# 5       S000003         V2     Subaru     Impreza            8180
# 6       S000003         V3     Toyota       Camry            5000
```

## Add a column of your own

Change a copy of a table in pandas, and pass it to `with_tables`. The book keeps your column through
every step, so results join to it by `submission_id`:

```python theme={null}
submissions = book.submissions
submissions["vehicle_count"] = submissions["submission_id"].map(book.vehicles["submission_id"].value_counts())
book = book.with_tables(submissions=submissions)
book.submissions[["submission_id", "policy_id", "vehicle_count"]].head(3)
#   submission_id  policy_id  vehicle_count
# 0       S000001  CA4176235              2
# 1       S000002  CA7257213              2
# 2       S000003  CA8422308              3
```

A book stays the same after you build it. `with_tables` returns a new book, and each table property
returns a copy.


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