惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Schneier on Security
F
Fortinet All Blogs
B
Blog
GbyAI
GbyAI
P
Proofpoint News Feed
量子位
The Register - Security
The Register - Security
宝玉的分享
宝玉的分享
大猫的无限游戏
大猫的无限游戏
云风的 BLOG
云风的 BLOG
V
Visual Studio Blog
B
Blog RSS Feed
WordPress大学
WordPress大学
Recorded Future
Recorded Future
Recent Announcements
Recent Announcements
V
Vulnerabilities – Threatpost
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
S
Secure Thoughts
雷峰网
雷峰网
Stack Overflow Blog
Stack Overflow Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Webroot Blog
Webroot Blog
AWS News Blog
AWS News Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
The GitHub Blog
The GitHub Blog
爱范儿
爱范儿
O
OpenAI News
月光博客
月光博客
H
Hacker News: Front Page
S
Security Affairs
W
WeLiveSecurity
The Hacker News
The Hacker News
aimingoo的专栏
aimingoo的专栏
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Help Net Security
Help Net Security
MongoDB | Blog
MongoDB | Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
D
Docker
T
The Blog of Author Tim Ferriss
Spread Privacy
Spread Privacy
Blog — PlanetScale
Blog — PlanetScale
J
Java Code Geeks
S
Securelist
Microsoft Azure Blog
Microsoft Azure Blog
TaoSecurity Blog
TaoSecurity Blog
T
Threat Research - Cisco Blogs
M
MIT News - Artificial intelligence
A
About on SuperTechFans

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Почему не всегда Pandas — лучший выбор (и когда стоит попробовать Polars)
Danila_Ly (Я · 2026-04-29 · via Все публикации подряд на Хабре

Уровень сложностиСредний

Время на прочтение9 мин

Охват и читатели17

Мнение

Привет, Хабр! Меня зовут Данила Ляпин, я Senior Data Scientist в Яндексе и автор курса «Специалист по Data Science» в Яндекс Практикуме.

В современном мире анализа данных пользу библиотеки Pandas трудно переоценить — она используется везде экспертами любого уровня: от стажёров до техлидов, а последние годы это де-факто стандарт в аналитике.

У Pandas есть огромная экосистема с большой базой знаний и интеграциями в различные библиотеки (тут и встроенная визуализация от matplotlib, и переход к данным в numpy формате, и много чего ещё). Практически каждый разведывательный анализ данных начинается с таких слов, как: read_csv, describe, head, isna().sum(). 

Но объём данных растёт ежегодно, память дорожает, а пайплайны усложняются. Чтобы загрузить локально большой датасет и обработать его, приходится не один раз словить "kernel crashed":

И вот на этом моменте самое время поговорить про Polars, потому что там с этим как раз всё в порядке (и не только с этим :-)

Что такое Polars и чем он хорош

Polars — это dataframe-библиотека (есть реализация на Python и Rust), ориентированная на скорость и эффективность памяти. Основана на Apache Arrow — совместимом колоночном представлении. Может работать в двух режимах:

  1. Pandas-like: «сделал операцию — получил результат».

  2. Ленивые вычисления: строим план вычислений, затем оптимизируем его и выполняем.

Глядя на логотип, можно увидеть отсылку к колоночной природе Polars :-)

Если посмотреть на официальную документацию (и отталкиваться от практики реального использования), у Polars довольно много плюсов:

  • работает быстро, потому что написан с нуля на Rust и без внешних зависимостей

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

  • очень понятный API: пишем запросы так, как удобно, а Polars сам определит наиболее эффективный способ их выполнения (с помощью оптимизатора запросов)

  • потоковый API позволяет обрабатывать результаты без того, чтобы хранить все данные в памяти одновременно

  • параллельная обработка всего использует «железо» по максимуму, распределяя нагрузку между доступными ядрами процессора без дополнительной настройки

  • векторизованный механизм выполнения запросов

  • при необходимости можно выполнять запросы на графических процессорах NVIDIA для достижения максимальной производительности (ну или там, где ещё есть CUDA)

  • Polars может принимать и генерировать данные в формате Apache Arrow, часто с использованием операций без копирования.

❗️ Обратите внимание, что Polars опирается на Arrow-совместимое колоночное представление данных, но не использует PyArrow как основной движок вычислений. Вместо этого вычисления и работа с памятью реализованы в самом Polars.

Установка Polars

Тут всё максимально просто: достаточно написать pip install polars и уже можно пользоваться.  Библиотека не имеет зависимостей (вообще никаких!), поэтому можно не переживать, что потом для запуска внезапно потребуется что-то ещё, а этого нет.

Импортируется чаще всего как import polars as pl, но никто не может помешать вам импортировать её любым другим способом (хоть так: import polars as pandas, но делать так мы точно не рекомендуем:-)

Основные типы данных

Если вы знакомы с пандасовскими объектами Series и DataFrame, то здесь мало что меняется: в Polars также реализованы свои типы этих данных. На практике очень удобно переходить к датафреймам Polars от Pandas (и наоборот):

polars_df = pl.from_pandas(pandas_df)  # Polars DataFrame
pandas_df = polars_df.to_pandas()  # Pandas DataFrame

Но кроме этих объектов в Polars есть несколько специфичных типов данных:

LazyFrame (ленивый датафрейм). Можем перейти к нему от обычного датафрейма (и наоборот):

lazy_polars_df = polars_df.lazy()  # LazyFrame
polars_df = lazy_polars_df.collect()  # DataFrame

Schema (названия столбцов и их типы данных). Можно проверить схему датафрейма, вызвав:

print(polars_df.schema)  
# Получим что-то вида:
# Schema({'name': String, 'birthdate': Date, 'weight': Float64, 'height': Float64})

Lazy API

Lazy API позволяет работать с LazyFrame-объектами. При использовании lazy API Polars не выполняет каждый запрос построчно, а обрабатывает весь запрос целиком, причём он выполняется только после команды collect(). Отсрочка выполнения до последнего момента может значительно повысить производительность, поэтому в большинстве случаев предпочтение отдаётся Lazy API. Давайте рассмотрим это на примере:

q = (
    pl.scan_csv("../data/iris.csv")
    .filter(pl.col("sepal_length") > 5)
    .group_by("species")
    .agg(pl.col("sepal_width").mean())
)
df = q.collect()

При использовании Lazy API вы можете использовать функцию объяснения, чтобы попросить Polars создать описание плана запроса, который будет выполнен после сбора результатов. Это может быть полезно, если вы хотите увидеть, какие типы оптимизации выполняет Polars по вашим запросам. Мы можем попросить Polars объяснить запрос, который мы определили выше: q.explain()

print(q.explain())

Использование lazy API позволяет выполнить несколько оптимизаций запроса. Некоторые из них выполняются заранее, другие — по мере поступления материализованных данных. Вот пример таких оптимизаций из жизни:

  • применить фильтры как можно раньше / на уровне сканирования файла

  • выбрать только те столбцы, которые нужны на уровне сканирования

  • загрузить только необходимый срез с уровня сканирования

  • определить, какие объединения следует выполнять в первую очередь, чтобы снизить нагрузку на память

  • привести типы данных к чему-то одному для успешного выполнения операций с минимальным потреблением памяти

  • оценить количество элементов для определения оптимальной стратегии группировки

Если нужно больше оптимизаций (а их мало не бывает), примеры с разборами есть в официальных доках.

Коротко про потоковый режим

Ещё одним преимуществом ленивого API является то, что он позволяет выполнять запросы в потоковом режиме. Вместо обработки всех данных одновременно Polars может выполнять запрос пакетно, что позволяет обрабатывать наборы данных, которые не помещаются в памяти. 

Чтобы сообщить Polars, что мы хотим выполнить запрос в потоковом режиме, мы передаём аргумент engine="streaming" для сбора:

q1 = (
    pl.scan_csv("../data/iris.csv")
    .filter(pl.col("sepal_length") > 5)
    .group_by("species")
    .agg(pl.col("sepal_width").mean())
)
df = q1.collect(engine="streaming")

Поддержка SQL-режима

Начинающим специалистам по данным SQL куда ближе, чем Python, поэтому данный режим может быть вполне полезен. 

❗️ Важно: в Polars отсутствует отдельный SQL-движок, поскольку он преобразует SQL-запросы в выражения, которые затем выполняются с помощью собственного обработчика. Такой подход гарантирует, что Polars сохраняет свои преимущества в производительности и масштабируемости как нативная библиотека DataFrame, одновременно предоставляя пользователям возможность работать с SQL.

Polars использует объект SQLContext для управления SQL-запросами. Контекст содержит сопоставление имен идентификаторов DataFrame и LazyFrame с соответствующими наборами данных. Вот как он создаётся:

ctx = pl.SQLContext()

Есть несколько способов регистрации объектов DataFrame во время инициализации SQLContext:

  • зарегистрировать все объекты LazyFrame и DataFrame в глобальном пространстве имён

  • зарегистрировать явно с помощью сопоставления словарей или ключевых аргументов (kwargs)

Посмотрим на оба варианта в коде:

df = pl.DataFrame({"a": [1, 2, 3]})
lf = pl.LazyFrame({"b": [4, 5, 6]})

# Зарегистрировать все датафреймы в глобальном пространстве имен: df как "df", lf как "lf"
ctx = pl.SQLContext(register_globals=True)

# Зарегистрировать явное сопоставление имени идентификатора с датафреймом
ctx = pl.SQLContext(frames={"table_one": df, "table_two": lf})

# Зарегистрировать фреймы с помощью kwargs: dataframe df как "df", а  lazyframe lf как "lf"
ctx = pl.SQLContext(df=df, lf=lf)

Ещё мы можем зарегистрировать DataFrames из библиотеки Pandas, предварительно преобразовав их в Polar-объекты (подробнее, как это работает: https://docs.pola.rs/user-guide/sql/intro):

import pandas as pd

df_pandas = pd.DataFrame({"c": [7, 8, 9]})
ctx = pl.SQLContext(df_pandas=pl.from_pandas(df_pandas))

После можем запускать наши SQL-запросы:

iris = pl.read_csv(
    "../data/iris.csv"
)
with pl.SQLContext(register_globals=True, eager=True) as ctx:
    df_small = ctx.execute("SELECT * from iris LIMIT 5")
    print(df_small)

SQL-запросы при этом можно выполнять из нескольких источников:

with pl.SQLContext(
    data=pl.scan_csv(DATA_FILE_2),
    districts=pl.scan_csv(DATA_FILE_2_DISTRICTS),
    groups=pl.scan_csv(DATA_FILE_2_GROUPS),
    eager=True,
) as ctx:
    query = """
    SELECT
        user_id,
        sex,
        districts.district,
        groups.group
    FROM
        data
    LEFT JOIN districts USING (user_id)
    LEFT JOIN groups USING (user_id)
    """
    print(ctx.execute(query))

На всякий случай напомню и повторюсь, что Polars не поддерживает всю спецификацию SQL, но поддерживает подмножество наиболее распространённых типов операторов. Уже доступны: SELECT, WHERE,ORDER,LIMIT,GROUP BY,UNION, JOIN, но оконных функций пока нет. Обещают добавить, но пока вот так.

Примеры кода из серии «одна задача — два решения»

Теперь посмотрим, насколько различается синтаксис библиотек Pandas и Polars при выполнении одних и тех же задач (спойлер: местами практически идентичен!).

1. Чтение большого файла + фильтр + агрегация

Цель: сравнить производительность при работе с большим parquet-файлом (5.5 млн строк, 65 колонок) при выполнении типичной аналитической задачи — фильтрации и агрегации данных.

(Файл DATA_FILE_1.parquet)

Классический код на Pandas:

data = pd.read_parquet(DATA_FILE_1)
data = data[data['target'] == 1]
data_aggr = data.groupby('user_id')['item_price'].sum()

Код на Polars:

data = pl.scan_parquet(DATA_FILE_1)
data = data.filter(pl.col('target') == 1)
data_aggr = data.group_by('user_id').agg(pl.col('item_price').sum()).collect()

Как видим, код получился практически одинаковый (с учётом синтаксиса, конечно).

2. Join нескольких таблиц + расчёт метрик

Цель: проверить эффективность объединения нескольких таблиц и последующего расчёта бизнес-метрик.

(Файлы DATA_FILE_2.csv, DATA_FILE_2_DISTRICTS.csv и DATA_FILE_2_GROUPS.csv)

Сначала напишем, используя Pandas:

data = pd.read_csv(DATA_FILE_2)
districts = pd.read_csv(DATA_FILE_2_DISTRICTS)
data = data.merge(districts, on='user_id', how='left')
groups = pd.read_csv(DATA_FILE_2_GROUPS)
data = data.merge(groups, on='user_id', how='left')

data_aggr = data.groupby('group', as_index=False).agg({'payment_page': 'sum', 'payment': 'sum'})
data_aggr['conversion'] = data_aggr['payment'] / data_aggr['payment_page']

А потом — с помощью Polars:

data = pl.scan_csv(DATA_FILE_2)
districts = pl.scan_csv(DATA_FILE_2_DISTRICTS)
data = data.join(districts, on='user_id', how='left')
groups = pl.scan_csv(DATA_FILE_2_GROUPS)
data = data.join(groups, on='user_id', how='left')

data_aggr = data.group_by('group').agg(pl.col('payment_page').sum(), pl.col('payment').sum())
data_aggr = data_aggr.with_columns(
    (pl.col('payment') / pl.col('payment_page')).alias('conversion')
).collect()

Тоже довольно близко друг к другу по коду (но не по производительности, можете проверить, хотя к ней мы тоже сейчас перейдём отдельно).

3. Оконные функции (ranking, rolling)

Цель: сравнить производительность оконных функций.

(Файл DATA_FILE_3.csv)

Сначала — на Pandas:

data = pd.read_parquet(DATA_FILE_1)
data["rank"] = data.groupby("user_id")["ials_score"].rank(method="dense", ascending=False)
data['rolling_mean'] = data.groupby('user_id')['item_price'].rolling(10).mean().values

И на Polars:

data = pl.scan_parquet(DATA_FILE_1)
data = data.with_columns([
          pl.col("ials_score")
            .rank(method="dense", descending=True)
            .over("user_id")
            .alias("rank"),

          pl.col("item_price")
            .rolling_mean(window_size=10)
            .over("user_id")
            .alias("rolling_mean"),
      ]).collect()

Выводы по скорости и эффективности будут ниже, для затравки скажу, что когда первый раз видишь такой отрыв — происходит довольно сильная переоценка ценностей :-)

4. Строковые операции (regex, split)

Цель: проверить, как обрабатываются текстовые данные с использованием регулярных выражений и разделения строк.

(Файл DATA_FILE_4.csv)

Код на Pandas:

data = pd.read_csv(DATA_FILE_4)
data['race/ethnicity'] = data['race/ethnicity'].str.split(' ').str[1]
data['parental level of education'] = data['parental level of education'].str.replace(r"[^\w\s]", "", regex=True)

И код на Polars:

data = pl.scan_csv(DATA_FILE_4)
data = data.with_columns(
    [
        pl.col("race/ethnicity")
          .str.split(" ")
          .list.get(1)
          .alias("race/ethnicity"),
        pl.col("parental level of education")
          .str.replace_all(r"[^\w\s]", "")
          .alias("parental level of education"),
    ]
).collect()

Результаты чуть хуже, чем в эксперименте выше, но спойлерить пока не буду, всё — в следующем разделе.

5. Работа со «сложными» типами (JSON)

Цель: сравнить производительность работы с вложенными структурами данных (json/словари). Например, у нас есть csv-файл с метаданными, а нам нужно извлечь параметры из вложенной структуры:

(Файл DATA_FILE_5.parquet)

(Файл DATA_FILE_5.parquet)

Сделаем это на Pandas:

data = pd.read_parquet(DATA_FILE_5)
for param in ['accompaniment', 'description', 'general_mood', 'genre_tags', 'lead_instrument', 'production_quality', 'tempo_and_rhythm', 'vocal_presence']:
    data[param] = data['enriched_metadata'].str[param]
data['main_genre'] = data['genre_tags'].str[0]

А потом — на Polars (и посмотрим на разницу в синтаксисе, тут она более явная):

data = pl.scan_parquet(DATA_FILE_5)

for param in ['accompaniment', 'description', 'general_mood', 'genre_tags', 'lead_instrument', 'production_quality', 'tempo_and_rhythm', 'vocal_presence']:
    data = data.with_columns(
        (pl.col('enriched_metadata').struct.field(param)).alias(param)
    )

data = data.with_columns(
    (pl.col('genre_tags').list.get(0, null_on_oob=True)).alias('main_genre')
).collect()

Профилирование кода и результаты сравнения

Для каждого эксперимента выше я провёл профилирование по времени и по памяти. Для замера времени выполнения использовалась магическая команда %%timeit Python, а для замера памяти — memory_profiler.

На какой конфигурации производился замер:

  • Python version: 3.13.0

  • Pandas version: 2.2.3

  • Polars version: 1.34.0

  • железо: MacBook M3 Pro

Результаты профилирования:

Эксперимент

Время Pandas

Время Polars

Память Pandas

Память Polars

Ускорение

1

Чтение файла + фильтр + агрегация

816 ms

6.69 ms

2374.75 MiB

0.02 MiB

120x

2

Join таблиц + расчёт метрик

329 ms

21.6 ms

16.77 MiB

0.00 MiB

15x

3

Оконные функции (ranking, rolling)

2.98 s

358 ms

2391.89 MiB

0.00 MiB

8x

4

Строковые операции (regex, split)

1.12 ms

558 μs

0.00 MiB

0.00 MiB

2x

5

Работа с JSON/структурами

11.3 ms

3.42 ms

0.02 MiB

0.00 MiB

3x

Ключевые выводы

Polars — точно не универсальный инструмент для всех задач, которые можно делать с помощью Pandas, но во многих ситуациях он оказывается гораздо эффективнее. 

Если коротко по выводам, то получилось такое:

  • Polars показывает ускорение от 2x до 120x в зависимости от задачи.

  • Наибольший выигрыш достигается при работе с большими файлами и фильтрации данных.

  • Polars значительно эффективнее использует память благодаря lazy evaluation.

  • Даже на малых датасетах Polars не уступает по скорости.

Если у вас появились вопросы по Polars (или хотите разобрать кейсы из своей практики) — пишите в комментариях, постараюсь ответить и помочь.