Polars — библиотека для трансформации, анализа и визуализации данных с быстрым и выразительным DataFrame API. Впервые была выпущена Ritchie Vink в 2020 году.

Установка Polars со всеми опциональными зависимостями из терминала:

uv pip install "polars[all]"

Импорт Polars в Python и проверка версий самой библиотеки и её зависимостей:

import polars as pl

pl.show_versions()

Запросы в Polars обычно читают данные, трансформируют их и записывают результат обратно. Полный запрос часто представляет собой единую цепочку вызовов методов:

fruit = pl.read_csv("fruit.csv")

fruit.filter(
    (pl.col("weight") > 1000) & pl.col("is_round")
).write_parquet("fruit.parquet")

По тексту шпаргалки df обозначает DataFrame, lfLazyFrame, o — второй DataFrame для объединения с df, а e — произвольное выражение. Так, e.abs() означает «вызвать .abs() у выражения», как в pl.col("x").abs().

Структуры данных

Polars хранит все данные либо в Series, либо в DataFrame.

СтруктураОписание
SeriesОдномерная. Содержит последовательность значений одного типа данных.
DataFrameДвумерная. Имеет строки и столбцы. Одна или несколько Series одинаковой длины.
LazyFrameНапоминает DataFrame, но не хранит данных. Чертёж для построения DataFrame.

В отличие от pandas, DataFrame в Polars не имеют индекса строк, а API отдаёт предпочтение неизменяемости и цепочкам вызовов методов вместо модификации на месте.

  • Создание Series путём передачи имени и последовательности значений:

    series = pl.Series("sales", [150.00, 300.00, 250.00])
  • Создание DataFrame из словаря столбцов, где каждое значение — Series или обычная последовательность Python. Также можно использовать любую из функций pl.read_*() для создания DataFrame из файла:

    df = pl.DataFrame({
        "sales": series,
        "id": [41, 42, 43]
    })
  • Поскольку индекса строк нет, при необходимости его добавляют явно как столбец:

    df.with_row_index("id")
  • Превращение DataFrame в LazyFrame. Альтернативно можно сразу начать с LazyFrame, используя любую из функций pl.scan_*():

    lf = df.lazy()

Eager и Lazy API

Eager API выполняется немедленно, тогда как lazy API сначала строит оптимизированный план запроса. Оптимизатор автоматически применяет predicate pushdown (фильтрацию как можно раньше) и projection pushdown (отбрасывание неиспользуемых столбцов).

Переход между двумя представлениями осуществляется через .lazy() и .collect(): .lazy() превращает DataFrame в LazyFrame, а .collect() выполняет LazyFrame и возвращает DataFrame.

  • Превращение DataFrame в LazyFrame и выполнение LazyFrame для получения DataFrame:

    lf = df.lazy()
    df = lf.collect()
  • Использование потокового движка для обработки данных вне оперативной памяти, чтобы обрабатывать датасеты крупнее доступной памяти:

    lf.collect(engine="streaming")
  • Вывод оптимизированного плана запроса в виде текста или визуализация его в виде графа, чтобы увидеть, что решил сделать оптимизатор:

    lf.explain()
    lf.show_graph()
  • Выполнение запроса с возвратом времени выполнения по каждому узлу, что показывает, куда фактически уходит время:

    lf.profile()

Типы данных

Polars реализует большую часть спецификации памяти Apache Arrow — эффективного колоночного формата для плоских и иерархических данных.

ГруппаТипПримечания
ЧисловыеDecimal128 бит, точность, масштаб
Float32Диапазон ±3.4×10³⁸
Float64Диапазон ±1.8×10³⁰⁸
Int8Диапазон ±128
Int16Диапазон ±32,768
Int32Диапазон ±2.1×10⁹
Int64Диапазон ±9.2×10¹⁸
Int128Диапазон ±3.4×10³⁸
UInt8Диапазон 0–255
UInt16Диапазон 0–65,535
UInt32Диапазон 0–4.3×10⁹
UInt64Диапазон 0–1.8×10¹⁹
ВременныеDateДни с начала эпохи Unix
DatetimeМикросекунды с начала эпохи
DurationДлительность / дельта времени
TimeВремя суток
ВложенныеArrayПоследовательность фиксированной длины
ListПоследовательность переменной длины
StructНесколько именованных полей
СтроковыеStringUTF-8 текст переменной длины
CategoricalСловарь строк
EnumФиксированный словарь строк
ПрочиеBooleanTrue / False
BinaryСырые байты
NullПредставляет Null / None

Проверка типов

  • Получение словаря имён столбцов и типов данных, либо только списка типов данных:

    df.schema
    df.dtypes
  • Вывод по одной строке на столбец, включая типы данных, что полезно для широких DataFrame, где вывод самого DataFrame нечитаем:

    df.glimpse()
  • Вычисление сводной статистики по каждому столбцу, включая количество null-значений:

    df.describe()
  • Вывод размера DataFrame в памяти в запрошенной единице измерения:

    df.estimated_size("mb")

Приведение типов

  • Приведение столбца к другому типу данных. По умолчанию приведение строгое, поэтому значение, которое не помещается, вызывает ошибку:

    df.select(pl.col("id").cast(pl.UInt64))
  • Передача strict=False для приведения без ошибки. Значения, переполняющие целевой тип, становятся null:

    df.select(pl.col("id").cast(pl.Int8, strict=False))

Чтение и запись данных

В Polars есть четыре семейства функций ввода-вывода, и выбор нужной зависит от того, работаете ли вы в eager или lazy режиме:

  • read_*() читает данные в DataFrame.
  • scan_*() создаёт LazyFrame, откладывая фактическое чтение до вызова collect.
  • write_*() записывает DataFrame на диск или в облачное хранилище.
  • sink_*() потоково передаёт данные на диск или в облачное хранилище, не удерживая всё в памяти.

Не каждый формат поддерживает все четыре операции:

Форматreadscanwritesink
Avro
Clipboard
CSV
Database
Delta Lake
Excel / ODS
Iceberg
IPC / Feather
JSON
NDJSON
Parquet
PyArrow Dataset

Среди именованных аргументов, которые принимают многие из этих функций: schema_overrides, n_rows, row_index_name, storage_options и compression.

  • Сканирование файлов в облачном хранилище путём передачи URI с шаблоном glob, с использованием storage_options для указания учётных данных и региона:

    pl.scan_parquet(
        "s3://bucket/*.parquet",
        storage_options={"aws_region": "us-east-2"}
    )
  • Потоковая передача запроса напрямую в партиционированный датасет Parquet, с записью одной директории на каждое отдельное значение ключевого столбца:

    lf.sink_parquet(pl.PartitionBy("out/", key="x"))

Трансформация данных

Выбор столбцов

Сохранение столбцов по имени, типу данных или позиции.

  • Выбор столбцов по имени:

    df.select("a", "b")
  • Выбор результата выражения, что позволяет трансформировать столбцы на выходе:

    df.select(pl.col("x") * 2)
  • Присвоение результату выражения имени с помощью именованного аргумента, что создаёт новый столбец:

    df.select(doubled=pl.col("x") * 2)
  • Выбор столбцов, имена которых соответствуют регулярному выражению. Шаблон должен начинаться с ^ и заканчиваться на $:

    df.select(pl.col("^.*_color$"))
  • Выбор всех столбцов:

    df.select(pl.all())

Селекторы столбцов дают больше гибкости. Их можно комбинировать с помощью операторов множеств |, &, -, ^ и ~.

  • Импорт модуля селекторов, затем выбор столбцов по типу данных или по шаблону имени. См. также cs.string(), cs.contains() и cs.first():

    import polars.selectors as cs
    
    df.select(cs.numeric())
    df.select(cs.starts_with("val"))
  • Удаление столбцов вместо их сохранения. Передача strict=False, чтобы несуществующие имена игнорировались, а не вызывали ошибку:

    df.drop("a", "y", strict=False)

Создание столбцов

Новые столбцы добавляются справа от существующих.

  • Добавление нового столбца, вычисленного из выражения, с указанием имени через именованный аргумент:

    df.with_columns(new=pl.col("a") + 1)
  • Замена существующего столбца путём создания выражения с тем же именем. Здесь null-значения в столбце a заменяются нулями:

    df.with_columns(pl.col("a").fill_null(0))
  • Добавление столбца с одним и тем же литеральным значением в каждой строке:

    df.with_columns(ones=pl.lit(1))
  • Добавление столбца индексов строк. Использование offset для начала отсчёта не с нуля:

    df.with_row_index(name="id", offset=1)

Фильтрация строк

Сохранение строк в соответствии со значениями одного или нескольких столбцов или выражений.

  • Фильтрация по существующему булеву столбцу путём передачи его имени:

    df.filter("valid")
  • Фильтрация с помощью одного выражения:

    df.filter(pl.col("x") > 5)
  • Передача нескольких выражений для их объединения через логическое И. AND можно также записать явно через &, в этом случае каждое сравнение требует собственных скобок:

    df.filter(pl.col("valid"), pl.col("x") > 5)
    df.filter(pl.col("valid") & (pl.col("x") > 5))
  • Использование | для логического ИЛИ:

    df.filter(pl.col("valid") | (pl.col("x") > 5))
  • Фильтрация с ограничениями через именованные аргументы — это сокращённая форма проверки равенства и объединения результатов через И:

    df.filter(valid=True, x=5)
  • Сохранение только строк без пропущенных значений, либо ограничение проверки конкретными столбцами:

    df.drop_nulls()
    df.drop_nulls("x")
  • Удаление дублирующихся строк. Использование subset для определения, какие столбцы задают дубликат, и keep для выбора, какой из дубликатов сохранится:

    df.unique(subset=["x"], keep="first")

Срезы и выборка строк

Сохранение строк на основе их позиции.

  • Сохранение первых или последних строк. По умолчанию — пять строк:

    df.head()
    df.tail(10)
  • Сохранение непрерывного среза путём указания смещения и длины. Это сохраняет строки с третьей по седьмую:

    df.slice(2, 5)
  • Сохранение каждой n-й строки:

    df.gather_every(2)
  • Взятие случайной выборки строк. Использование with_replacement=True, чтобы одна и та же строка могла быть выбрана более одного раза, или fraction для выборки доли вместо фиксированного числа:

    df.sample(10)
    df.sample(10, with_replacement=True)
    df.sample(fraction=0.2)

Сортировка строк

Переупорядочивание строк в соответствии со значениями одного или нескольких столбцов или выражений.

  • Сортировка по одному столбцу, по умолчанию по возрастанию, либо по нескольким столбцам последовательно:

    df.sort("x")
    df.sort("x", "y")
  • Перемещение null-значений в конец, а не в начало:

    df.sort("x", nulls_last=True)
  • Обращение порядка. При сортировке по нескольким столбцам можно передать список булевых значений, чтобы задать направление для каждого столбца:

    df.sort("x", descending=True)
    df.sort("x", "y", descending=[False, True])
  • Сортировка по результату выражения, а не по столбцу, например по вычисленному отношению или длине списка:

    df.sort(pl.col("x") / pl.col("y"))
    df.sort(pl.col("l").list.len())
  • Сохранение только k наибольших или наименьших строк по столбцу, что дешевле, чем сортировать всё, а затем брать срез:

    df.top_k(5, by="score")
    df.bottom_k(5, by="score")

Изменение формы

Переход от широкого формата к длинному и обратно.

  • Расширение DataFrame в высоту путём превращения значений одного или нескольких столбцов в строки, с сохранением столбцов index в качестве идентификаторов:

    df.unpivot(on=["c"], index="id")
  • Расширение DataFrame в ширину путём превращения значений столбца в новые столбцы. Если комбинация on и index не уникальна, нужно указать aggregate_function, чтобы определить, как объединять коллизии:

    df.pivot(on="c", index="id", values="x")
    df.pivot(on="c", index="id", values="x", aggregate_function="sum")
  • Раскрытие столбца-списка, чтобы каждый элемент получил собственную строку, с повторением остальных столбцов:

    df.explode("l")
  • Раскрытие столбца-структуры, чтобы каждое поле стало отдельным столбцом:

    df.unnest("s")
  • Транспонирование строк и столбцов. Использование include_header=True для сохранения исходных имён столбцов в качестве отдельного столбца:

    df.transpose(include_header=True)
  • Разбиение DataFrame на список меньших DataFrame, по одному на каждое отдельное значение заданного столбца:

    df.partition_by("group")

Сводки и агрегация

Разделить. Применить. Объединить.

  • Разбиение DataFrame на группы по одному или нескольким столбцам. Это даёт объект GroupBy, к которому затем применяется агрегация:

    dfg = df.group_by("x")
    dfg = df.group_by("x", "y")
  • Применение готовой сводки к каждой группе. Подсчёт строк в группе, взятие первых строк каждой группы или вычисление среднего по каждому столбцу в группе:

    dfg.len()
    dfg.head(2)
    dfg.mean()
  • Применение собственной функции к каждой группе, когда ни одна встроенная агрегация не подходит:

    dfg.map_groups(...)
  • Использование agg() для полного контроля над агрегацией. Передача выражения без агрегирующего метода собирает значения в список, а именование результата через именованный аргумент даёт новому столбцу осмысленное имя:

    dfg.agg(...)
    dfg.agg(pl.col("y"))
    dfg.agg(avg=pl.col("y").mean())
  • Использование оконного выражения с over() для добавления агрегации в качестве нового столбца к исходному DataFrame без схлопывания строк:

    df.with_columns(avg=pl.col("y").mean().over("x"))
  • Группировка по временному значению или индексу вместо категории. group_by_dynamic() создаёт окна фиксированной длительности, а group_by добавляет поверх обычную группировку:

    df.group_by_dynamic("timestamp", every="1h", group_by="store")
  • Использование rolling() для окна, которое сдвигается с каждой строкой, а не фиксированными шагами. Это вычисляет скользящую сумму продаж за семь дней по каждому магазину:

    df.rolling(index_column="date", period="7d", group_by="store").agg(
        pl.col("sales").sum()
    )
  • Создание строк, отсутствующих в регулярном временном ряде, чтобы был представлен каждый интервал:

    df.upsample(
        time_column="date", every="1d", group_by="store", maintain_order=True
    )
  • Агрегация по столбцам, а не вдоль них. Горизонтальные функции объединяют несколько столбцов в пределах каждой строки:

    df.select(pl.sum_horizontal(cs.numeric()))
    df.select(pl.any_horizontal(cs.boolean()))

Объединение и конкатенация

Объединение нескольких DataFrame в один.

  • Объединение двух DataFrame по общему ключу. По умолчанию используется inner join, который сохраняет только строки, совпадающие с обеих сторон:

    df.join(o, on="key")
  • Использование how для выбора другой стратегии соединения. Left join сохраняет каждую строку df:

    df.join(o, on="key", how="left")
  • Если ключ имеет разное имя в каждом DataFrame, обе стороны указываются явно:

    df.join(o, left_on="a", right_on="b")
  • Full outer join сохраняет все строки с обеих сторон. Добавление coalesce=True объединяет два столбца-ключа в один:

    df.join(o, on="key", how="full", coalesce=True)
  • Фильтрующие join возвращают столбцы только из df, используя o исключительно как фильтр. Semi join сохраняет строки df, для которых есть совпадение, а anti join сохраняет строки, для которых совпадения нет:

    df.join(o, on="key", how="semi")
    df.join(o, on="key", how="anti")
  • Cross join создаёт декартово произведение обоих DataFrame и поэтому не требует ключа:

    df.join(o, how="cross")
  • Соединение по ближайшему совпадению, а не по точному, что является обычным способом сопоставления двух временных рядов. Использование by для точного сопоставления сначала по некоторым столбцам:

    df.join_asof(o, on="ts", by="i")
  • Соединение по произвольному предикату для неравенства или других non-equi соединений:

    df.join_where(o, pl.col("a") >= pl.col("b"))

Распространённые именованные аргументы для df.join() — это left_on, right_on, coalesce, join_nulls, suffix и validate, где validate принимает "m:m", "m:1", "1:m" и "1:1".

  • Складывание DataFrame друг на друга, что требует совпадающих столбцов:

    pl.concat([df, o])
  • Размещение DataFrame рядом друг с другом, либо объединение их столбцов с заполнением пропусков null-значениями:

    pl.concat([df, o], how="horizontal")
    pl.concat([df, o], how="diagonal")
  • Использование смягчённой стратегии для приведения несовпадающих типов данных вместо вызова ошибки:

    pl.concat([df, o], how="vertical_relaxed")
  • Обновление значений в df непустыми значениями из другого DataFrame, с сопоставлением строк по ключу:

    df.update(o, on="id", how="left")

Выражения

Определение выражения

Выражение — это дерево операций, описывающее, как построить одну или несколько Series.

  • Series: массив одного типа; столбец или самостоятельная сущность
  • Дерево операций: одиночное, линейное или разветвлённое
  • Описывает: пассивный рецепт; требует функцию для выполнения
  • Строит: результат может быть внутренним, а не новым столбцом
  • Одна или несколько: одно выражение может создавать несколько Series

Начало выражений

Каждое выражение начинается со столбца, со всех столбцов или с литерального значения.

  • Построение выражения на основе существующего столбца, всех столбцов или литерального значения. Обратите внимание, что pl.col("*") и pl.all() эквивалентны:

    pl.col("name")
    pl.col("*")
    pl.all()
    pl.lit("ok")
  • Генерация диапазона целых чисел, где конечное значение исключается. Это создаёт [0, 1, 2, 3, 4]:

    pl.arange(0, 5)
  • Генерация диапазона дат. Форма единственного числа создаёт один диапазон, а форма множественного числа создаёт столбец диапазонов, по одному на строку. Для целых чисел, времени и datetime есть собственные функции *_range() и *_ranges():

    pl.date_range(...)
    pl.date_ranges(...)

Объединение выражений с помощью арифметики

Арифметические операции можно выполнять как с выражениями, так и с обычными значениями Python. У каждого оператора есть эквивалентный метод, что удобно, когда нужно сохранить цепочку вызовов методов неразрывной.

ОператорМетодОписание
+e.add(...)Сложение
-e.sub(...)Вычитание
*e.mul(...)Умножение
/e.truediv(...)Деление
//e.floordiv(...)Целочисленное деление
**e.pow(...)Степень
%e.mod(...)Остаток от деления
N/Ae.dot(...)Скалярное произведение

Объединение выражений через сравнение

В отличие от Python, сравнения нельзя объединять в цепочку. Нужно писать (pl.col("x") > 0) & (pl.col("x") < 10), а не 0 < pl.col("x") < 10.

ОператорМетодОписание
<e.lt(...)Меньше
<=e.le(...)Меньше или равно
==e.eq(...)Равно
>=e.ge(...)Больше или равно
>e.gt(...)Больше
!=e.ne(...)Не равно

Объединение выражений с помощью булевой логики

Обратите внимание, что and, or и not являются зарезервированными словами в Python, отсюда подчёркивания в именах методов.

ОператорМетодОписание
&e.and_(...)Логическое И
|e.or_(...)Логическое ИЛИ
~e.not_()Логическое НЕ
^e.xor(...)Логическое исключающее ИЛИ

Условное выражение

Цепочка when() и then() строит условное выражение, которое завершается otherwise(). Условия проверяются по порядку, и побеждает первое совпадение, поэтому наиболее специфичное условие ставится первым:

df.with_columns(
    pl.when(pl.col("age") < 18).then(pl.lit("minor"))
      .when(pl.col("age") < 65).then(pl.lit("adult"))
      .otherwise(pl.lit("senior"))
      .alias("group")
)

Математика, тригонометрия и округление

  • e.abs(), e.sign(), e.exp(): абсолютное значение, знак и экспонента.
  • e.cbrt(), e.sqrt(): кубический и квадратный корень.
  • e.log(...), e.log10(), e.log1p(): логарифмы.
  • e.cos(), e.sin(), e.tan(): тригонометрические функции.
  • e.cosh(), e.sinh(), e.tanh(): гиперболические функции.
  • e.arccos(), e.arcsin(), e.arctan(): обратные тригонометрические функции.
  • e.arccosh(), e.arcsinh(), e.arctanh(): обратные гиперболические функции.
  • e.degrees(), e.radians(): перевод между радианами и градусами.
  • e.ceil(), e.floor(), e.round(...): округление.
  • e.clip(...), e.cut(...), e.qcut(...): ограничение значений диапазоном, либо разбиение на интервалы по своему выбору или на квантили.

Пропущенные значения и формы

В Polars null означает отсутствие значения, тогда как NaN — это float, возникающий из неопределённых математических операций, таких как 0 / 0. Эти два случая обрабатываются отдельными методами.

  • e.fill_nan(...), e.fill_null(...): заполнение пропущенных значений.
  • e.is_finite(), e.is_infinite(): проверка на конечность и бесконечность.
  • e.is_nan(), e.is_not_nan(): проверка на NaN.
  • e.is_null(), e.is_not_null(): проверка на null.
  • e.drop_nans(), e.drop_nulls(): удаление пропущенных значений.
  • e.flatten(), e.reshape(...): изменение формы списка или столбца.
  • e.explode(), e.implode(): превращение списка в строки, либо сбор строк в список.

Сдвиги, накопление и скользящие окна

  • e.backward_fill(...), e.forward_fill(...): заполнение null следующим или предыдущим значением.
  • e.interpolate(...), e.shift(...): интерполяция между известными значениями, либо сдвиг значений вверх или вниз.
  • e.cum_count(...), e.cum_sum(...): накопленный счёт и сумма.
  • e.cum_max(...), e.cum_min(...): накопленный максимум и минимум.
  • e.diff(...), e.pct_change(...): разница и процентное изменение между строками.
  • e.ewm_mean(...), e.ewm_std(...), e.ewm_var(...): экспоненциально взвешенные скользящие статистики.
  • e.rolling_max(...), e.rolling_min(...): скользящий максимум и минимум.
  • e.rolling_mean(...), e.rolling_median(...): скользящее среднее и медиана.
  • e.rolling_std(...), e.rolling_var(...): скользящее стандартное отклонение и дисперсия.
  • e.rolling_map(...): применение собственной функции к скользящему окну.

Сортировка, ранжирование и булевы операции

  • e.sort(...), e.sort_by(...): сортировка столбца по собственным значениям, либо по значениям других столбцов.
  • e.arg_sort(...): возврат индексов строк, которые отсортировали бы столбец.
  • e.shuffle(...), e.reverse(): случайное перемешивание значений, либо обращение их порядка.
  • e.rank(...): присвоение рангов данным.
  • e.is_duplicated(), e.is_unique(): отметка дублирующихся и уникальных значений.
  • e.is_first_distinct(), e.is_last_distinct(): отметка первого или последнего вхождения каждого отдельного значения.

Сводки и статистика

  • e.all(...), e.any(...): истина, если все или хотя бы одно из значений истинно.
  • e.max(), e.min(), e.mean(): максимум, минимум и среднее.
  • e.nan_max(), e.nan_min(): максимум и минимум, распространяющие NaN.
  • e.median(), e.std(), e.var(...): медиана, стандартное отклонение и дисперсия.
  • e.entropy(...), e.kurtosis(...), e.skew(...): статистики распределения.
  • e.product(), e.quantile(...), e.sum(): произведение, квантиль и сумма.
  • e.arg_max(), e.arg_min(): индекс максимального и минимального значения.
  • e.first(), e.last(), e.get(...): получение значения по позиции.
  • e.mode(): наиболее часто встречающиеся значения.

Подсчёт, уникальность и выборка

  • e.len(): подсчёт всех строк, включая null.
  • e.count(): подсчёт только непустых значений.
  • e.null_count(): подсчёт null-значений.
  • e.n_unique(), e.approx_n_unique(): количество уникальных значений, точное или приближённое.
  • e.arg_unique(), e.unique(...): индексы уникальных значений, либо сами уникальные значения.
  • e.unique_counts(), e.value_counts(...): частота встречаемости каждого уникального значения.
  • e.head(...), e.tail(...), e.limit(...): выбор строк с начала или с конца.
  • e.bottom_k(...), e.top_k(...): k наименьших или наибольших значений.
  • e.gather(...), e.gather_every(...): взятие значений по индексу, либо каждого n-го значения.
  • e.sample(...), e.slice(...): выборка или срез внутри выражения.
  • e.arg_true(): индексы, где значение истинно.
  • e.replace(...): замена значений по словарю.
  • e.search_sorted(...): поиск индекса вставки в отсортированном столбце.

Массивы и списки

Array имеют фиксированную длину; List — нет. Методы для Array находятся в пространстве имён arr, а для List — в пространстве имён list.

  • Приведение столбца к массиву фиксированной длины с последующим использованием пространства имён array:

    e.cast(pl.Array(pl.Int8, 3))
    e.arr.max()
    e.arr.sort()
  • Объединение нескольких столбцов в один столбец-список:

    pl.list("a", "b")
  • Работа с содержимым столбца-списка: получение длины каждого списка, получение элемента по индексу, сортировка элементов внутри каждого списка, объединение их в единую строку, либо проверка наличия значения:

    e.list.len()
    e.list.get(0)
    e.list.sort()
    e.list.join("-")
    e.list.contains(5)

Categorical и Enum

Categorical выводит свои категории из данных и сортируется лексикографически, тогда как Enum задаётся заранее и сортируется в порядке объявления.

  • Приведение столбца String к Categorical, либо к Enum с точным набором допустимых значений:

    e.cast(pl.Categorical)
    e.cast(pl.Enum(["Good", "Bad"]))
  • Получение категорий, которые в итоге получил столбец Categorical:

    e.cat.get_categories()

Даты, datetime, время и длительности

Date отслеживает дни, тогда как Datetime отслеживает микросекунды. Методы для работы с ними находятся в пространстве имён dt.

  • Построение Date, Datetime или Duration из их компонентов:

    pl.date(2026, 12, 31)
    pl.datetime(2026, 6, 30, 23, 59, 0)
    pl.duration(days=1)
  • Извлечение отдельного компонента, например месяца:

    e.dt.month()
  • Замена отдельных единиц времени, оставляя остальные без изменений:

    e.dt.replace(...)
  • Форматирование datetime в строку по спецификации формата:

    e.dt.strftime(...)
  • Перевод datetime в другой часовой пояс:

    e.dt.convert_time_zone("UTC")
  • Выражение длительности в виде количества секунд:

    e.dt.total_seconds()

Строки

Строки хранятся в UTF-8, поэтому длина и срезы считаются по символам, а не по байтам. Методы для строк находятся в пространстве имён str.

  • e.str.contains(...): проверка, соответствует ли каждое значение регулярному выражению.
  • e.str.split(...): разбиение каждого значения по разделителю на список.
  • e.str.to_uppercase(): перевод каждого значения в верхний регистр.
  • e.str.to_datetime(): парсинг каждого значения в Datetime.
  • e.str.extract(r"(\d+)"): извлечение первой захваченной группы регулярного выражения.
  • e.str.strip_chars(...): удаление пробелов или указанных символов с обоих концов.

Структуры

Struct объединяет несколько столбцов в один элемент строки. Методы для структур находятся в пространстве имён struct.

  • Объединение столбцов в Struct, затем извлечение отдельного поля обратно:

    pl.struct("a", "b")
    e.struct.field(...)
  • Переименование полей Struct, либо добавление и изменение полей:

    e.struct.rename_fields(...)
    e.struct.with_fields(...)

Бинарные данные

Пространство имён bin используется для сырых байтовых данных и для конвертации base64 и hex.

  • Декодирование строки base64, либо кодирование байтов в шестнадцатеричную строку:

    e.bin.base64_decode()
    e.bin.hex_encode()

Имена вывода

Управление конечными именами столбцов выражений через пространство имён name.

  • Добавление префикса к существующему имени, либо перевод его в нижний регистр:

    e.name.prefix(...)
    e.name.to_lowercase()

Meta

Методы интроспекции, используемые в основном при написании плагинов, находятся в пространстве имён meta.

  • e.meta.output_name(): получение имени, которое выведет выражение.
  • e.meta.is_regex(): проверка, является ли выражение регулярным выражением.
  • e.meta.has_multiple_outputs(): проверка, создаёт ли выражение несколько выводов.

Оформление данных

Great Tables превращает DataFrame в таблицу, готовую для презентации. Отправная точка — GT(df), к которому цепочкой добавляются методы для настройки заголовка и шапки, форматирования значений и добавления цвета:

from great_tables import GT

(
    GT(df)
    .tab_stub(rowname_col="...")
    .cols_label(...)
    .tab_header(title="...")
    .fmt_number(...)
    .fmt_nanoplot(...)
    .data_color(columns="...", palette="...")
)
Пример Great Tables

Визуализация данных

Встроенные методы построения графиков используют под капотом Altair и доступны из пространства имён plot:

df.plot.scatter(x="...", y="...", color="...")
Диаграмма рассеяния Altair

Многие другие пакеты умеют работать с DataFrame Polars напрямую, включая Plotnine, Plotly, hvPlot, Seaborn и Matplotlib. Для того, что не умеет, можно сначала сконвертировать в pandas с помощью df.to_pandas().

from plotnine import *

ggplot(df, aes(x="", y="", color="")) + geom_point()
Точечная диаграмма Plotnine

Polars Cloud

Выполнение запроса на кластере инстансов в собственном окружении. Требуемые вычислительные ресурсы описываются через ComputeContext, после чего LazyFrame запускается удалённо на этом контексте:

import polars_cloud as pc

ctx = pc.ComputeContext(
    workspace="workspace_name",
    cpus=4,
    memory=16,
    cluster_size=32
)

lf.remote(ctx).execute().await_result()

Книга

Шпаргалка основана на книге Python Polars: The Definitive Guide авторов Jeroen Janssens и Thijs Nieuwdorp, выпущенной издательством O'Reilly. Книга доступна в печатном и электронном форматах в любимом книжном магазине. Подробности — на сайте polarsguide.com.