Guides
Schemas
A schema is the columns of a frame, each with a name and a data type. A schema has no order. Declare it once, and use it in the type of a frame.
Declare a schema with a class
Section titled “Declare a schema with a class”A Columns class lists the columns. Each field is a column, and its type is a Polars data type. Columns declares no column of its own. A subclass inherits the columns of its base:
Revealed type
TypedDataFrame[TypedDict(Blotter, {'symbol': String, 'price': Float64, 'quantity': Int64, 'venue': String}, closed=True), None]TypedDataFrame[Blotter] is a closed frame: it has exactly the four columns. To accept a frame with more columns, see Open frames.
TypedDataFrame with no argument names no column. The checker reads it as the plain frame pl.DataFrame, and does not track it. TypedDataFrame[()] is a frame with no column.
Declare a schema with a dict
Section titled “Declare a schema with a dict”A column name that is not a Python identifier cannot be a field. Declare such a schema with columns(), from a name and a dict:
Revealed type
TypedDataFrame[TypedDict({'id': Int64, '2024': Float64}, closed=True), None]Give the parameters of a data type
Section titled “Give the parameters of a data type”Some data types have parameters: the time unit of a Datetime, the precision of a Decimal, the categories of an Enum. A field is a type annotation, so it names these data types with a marker:
Revealed type
TypedDataFrame[TypedDict(Fills, {'time': Datetime[Literal['us'], None], 'cost': Decimal[Literal[10], Literal[2]], 'lots': List[Int64], 'side': Enum[tuple[Literal['buy'], Literal['sell']]]}, closed=True), None]The checker keeps the parameters. A Datetime in microseconds is a different data type from a Datetime in milliseconds. See Data types for each marker.
Keep a data type in a name
Section titled “Keep a data type in a name”A name can hold a data type. Write it as you write it everywhere else in Polars:
Revealed type
TypedDataFrame[TypedDict(Trade, {'time': Datetime[Literal['us'], None], 'cost': Decimal[Literal[20], Literal[4]]}, closed=True), None]Every declaration that takes a data type as an argument reads such a name, with its parameters: columns(...), column(...) and other_columns(all_of=...). A name bound to another name resolves too.
A field is a type annotation, and mypy refuses a variable there. In a Columns class, name the data type with its marker: Stamped = Datetime[Literal["us"], None] is a type alias, and time: Stamped declares the field.
Write a generic schema
Section titled “Write a generic schema”A schema can take a data type as a parameter. Each use of the schema gives the parameter:
Revealed type
TypedDataFrame[TypedDict(Keyed, {'key': String, 'value': UInt32}, closed=True), None]The checker binds T to UInt32 at the call, so the result has the data type of the caller.
Rules of a schema
Section titled “Rules of a schema”A Polars column is never optional, and the declared columns of a frame are complete. So a Columns class has two rules:
- Each field has a Polars data type, or a marker of one.
- The class does not use
total=False,closed=False,Required[...]orNotRequired[...].
The checker reports a class that breaks a rule where a frame type uses the class: