Course
Если вы регулярно используете Python для анализа данных, как и я, то быстро замечаете: чтение CSV — одна из самых частых задач. Но по мере роста наборов данных этот подход может становиться медленным или требовательным к памяти.
Polars — это быстрая, современная библиотека DataFrame для Python, созданная как высокопроизводительная альтернатива Pandas. Она гораздо легче справляется с большими наборами данных, поскольку изначально ориентирована на скорость и низкое потребление памяти.
Базовая функция Polars pl.read_csv() предоставляет простой способ загрузить CSV в DataFrame с набором встроенных опций для управления разбором, типами данных и использованием памяти.
В этом руководстве мы рассмотрим, как читать CSV-файлы, управлять разбором и работать с большими наборами данных с помощью функции Polars pl.read_csv(). Если вы только начинаете, загляните на наш курс Introduction to Polars, чтобы научиться преобразовывать данные и извлекать инсайты с Polars.
Базовое использование pl.read_csv()
Прежде чем идти дальше, посмотрите наш учебник Python Polars, чтобы настроить окружение.
Теперь посмотрим, как работает функция pl.read_csv():
# import the module
import polars as pl
# Load CSV into a Polars DataFrame
fuel_data = pl.read_csv("Fuel_Consumption_2000-2022.csv")
# Preview first few rows
print(fuel_data.head())
В примере выше Polars считывает файл и загружает его в DataFrame. Функция возвращает Polars DataFrame — табличную структуру данных, похожую на то, что вы получаете в pandas.
По умолчанию pl.read_csv():
-
Предполагает, что первая строка содержит имена столбцов (
has_header=True) -
Автоматически определяет типы данных столбцов
-
Использует запятую (
,) как разделитель -
Считывает весь файл целиком в память
Часто используемые параметры в pl.read_csv()
Теперь, когда вы узнали, как pl.read_csv() загружает данные, посмотрим, как с помощью параметров можно настроить разбор данных Polars под ваши нужды.
Путь к файлу и источник
Polars позволяет загружать данные из разных источников. Можно передать локальный строковый путь, объект Pathlib или даже URL. Например, код ниже считывает с веба большой CSV-файл с ВВП разных стран по годам.
# Reading from a URL
url = "https://raw.githubusercontent.com/datasets/gdp/master/data/gdp.csv"
gdp_data = pl.read_csv(url)
Разделители и сепараторы
Не все CSV используют запятые. Вы можете задать аргумент separator, чтобы обрабатывать табуляции, точки с запятой, вертикальные черты и другие символы. Пример ниже показывает, как указывать разделители при чтении файлов
# Reading a Semicolon-separated file
sales_data = pl.read_csv("2024_sales.csv", separator=";")
# Reading a Tab-separated file (TSV)
orders_data = pl.read_csv("all_orders.tsv", separator="\t")
Обработка заголовка
Как мы видели, Polars предполагает, что первая строка данных содержит имена столбцов. Если в вашем файле нет строки заголовка, используйте параметр has_header=False, как показано ниже. Polars автоматически присвоит имена столбцов вроде column_1, column_2, column_3 и так далее.
# Load file without a header
orders_data = pl.read_csv("all_orders.csv", has_header=False)
Вы также можете переименовать столбцы, передав конкретные имена. Например:
# Providing specific column names
sales_data = pl.read_csv("sales_April.csv", new_columns=[
"OrderDate", "OrderNumber", "ProductKey", "SalespersonKey", "Salesperson"])
Кодировка
Разные CSV могут использовать разные кодировки текста. Если видите странные символы или ошибки, укажите кодировку:
# Load CSV into a Polars DataFrame
fuel_data = pl.read_csv("Fuel_Consumption_2000-2022.csv", encoding="utf8")
Другие распространённые варианты — "latin1" и "utf8-lossy", которые корректно обрабатывают некорректные символы.
Как выбирать столбцы при чтении CSV в Polars
При работе с большими файлами CSV часто нет нужды в каждом столбце. В Polars можно загрузить только требуемые столбцы с помощью параметра columns.
# Load only specific columns
fuel_data = pl.read_csv("Fuel_Consumption_2000-2022.csv",
columns=["YEAR", "MAKE", "MODEL"]
)
Если выбирать нужные столбцы на этапе загрузки, это сокращает потребление памяти, так как лишние данные не загружаются. Такой подход также ускоряет чтение файла и улучшает производительность конвейера в целом.
Как работать с типами данных (схемой) в CSV Polars
Polars — строго типизированная библиотека, то есть каждый столбец должен иметь согласованный тип данных, например все целые числа или все строки.
Автоматический вывод типов
По умолчанию Polars анализирует данные и автоматически определяет типы столбцов. Этот метод хорошо работает в большинстве случаев, но иногда может неправильно трактовать столбцы, например воспринимать идентификаторы как целые числа вместо строк.
Явное задание схемы
Если вам нужна предсказуемость в DataFrame, задайте схему данных вручную. Это обеспечивает согласованность между несколькими файлами и помогает избежать ошибок типов на последующих этапах обработки.
В большинстве случаев используйте schema_overrides, чтобы указать тип данных для отдельных столбцов, позволив Polars вывести типы остальных
import polars as pl
# Manually overriding specific data types
empl_data = pl.read_csv(
"all_employees.csv",
schema_overrides={
"id": pl.Int64,
"name": pl.String,
"age": pl.Int64,
"salary": pl.Float64
}
)
Или используйте schema, чтобы определить всю структуру DataFrame целиком.
# Manually define the full schema
empl_data = pl.read_csv(
"all_employees.csv",
schema={
"id": pl.Int64,
"name": pl.String,
"age": pl.Int64,
"salary": pl.Float64
}
)
Как обрабатывать пропуски в CSV Polars
По умолчанию Polars автоматически обнаруживает пропуски и представляет их как null. Иногда пропуски обозначаются особыми строками, такими как "NA", "N/A" или "missing". Вы можете задать их через null_values, чтобы трактовать как null.
# Treating "N/A" and "EMPTY" as nulls
survey_data = pl.read_csv(
"survey_results.csv",
null_values=["N/A", "EMPTY", "null"]
)
Правильная обработка пропусков обеспечивает согласованность типов данных и предотвращает некорректные расчёты, снижая число ошибок при анализе и моделировании.
Чтение больших CSV-файлов в Polars
При работе с наборами данных, превышающими доступную оперативную память, Polars особенно силён: он обрабатывает данные, не загружая весь файл целиком.
Ленивая загрузка с scan_csv()
Вместо немедленной загрузки данных в память, как read_csv(), Polars предлагает ленивую альтернативу — scan_csv(), которая строит оптимизированный план запроса и выполняет только необходимые операции.
В примере ниже pl.scan_csv сканирует CSV без загрузки, строит запрос для выборки только столбцов «YEAR», «MAKE» и «MODEL» для бренда «ACURA», а затем выполняет его. В память попадёт только отфильтрованный срез данных, а не весь файл.
# Lazily reference the file (no data loaded yet)
fuel_consumption = pl.scan_csv("Fuel_Consumption_2000-2022.csv")
fuel_consumption_filtered = fuel_consumption.select(
["YEAR", "MAKE", "MODEL"]).filter(pl.col("MAKE") == "ACURA")
# Execute the query and load only the required data
fuel_consumption_acura = fuel_consumption_filtered.collect()
Рекомендуется использовать scan_csv(), когда:
- Вы работаете с большими файлами, которые не умещаются в памяти
- Применяете несколько преобразований, таких как фильтрация, выборка и агрегация
- Нужна оптимизация запроса до выполнения
Потоковая обработка и экономия памяти
Polars также позволяет обрабатывать данные потоково, частями, удерживая пиковое потребление памяти постоянным вне зависимости от размера файла.
Для больших CSV начните со scan_csv(), чтобы создать ленивый запрос. При вызове scan_csv() файл полностью не загружается.
# Read data in chunks
fuel_consumption = pl.scan_csv("Fuel_Consumption_2000-2022.csv",
low_memory=True)
Поскольку описанный выше способ всё ещё использует read_csv, лучший подход — сочетать ленивое выполнение со streaming.
В примере ниже Polars обрабатывает файл конвейером, пакетами построчно, держа в памяти только отфильтрованные строки (где "CYLINDERS" > 3) в каждый момент времени.
# Lazily reference the file (no data loaded yet)
fuel_consumption = pl.scan_csv("Fuel_Consumption_2000-2022.csv")
result = fuel_consumption.filter(pl.col("CYLINDERS") > 3)
# Stream execution instead of loading everything at once
fuel_consumption_high = result.collect(engine="streaming")
Преимущество по производительности vs. Pandas
По сравнению с pandas, Polars часто быстрее при чтении и обработке CSV, как увидим в следующем разделе.
Polars read_csv vs Pandas read_csv
Таблица ниже суммирует различия между Polars и Pandas при чтении CSV в Python.
|
Аспект |
Polars |
Pandas |
|
Скорость |
Быстрее за счёт многопоточности и оптимизированного парсинга |
Медленнее на больших файлах (в основном однопоточно) |
|
Использование памяти |
Меньший след; поддерживает ленивый режим + потоковую обработку |
Жадно загружает весь набор данных в память |
|
Синтаксис |
|
|
|
Модель выполнения |
Поддерживает ленивое выполнение ( |
Только жадное (немедленное) выполнение |
|
Оптимизация |
Встроенная оптимизация запросов (проекция, фильтрация) |
Ограниченная автоматическая оптимизация |
|
Лучший сценарий |
Большие наборы данных, критичные к производительности процессы |
Малые наборы данных, быстрый анализ |
Рекомендуем прочитать наш материал о различиях между Pandas и Polars, чтобы понять, какой инструмент лучше подходит вашим аналитическим задачам.
Чтение CSV из разных источников
Как мы уже видели, Polars можно использовать для чтения CSV из разных источников. В примерах выше показано чтение CSV из локальных файлов и по URL.
Кроме того, Polars автоматически обрабатывает сжатые CSV-файлы. Например, код ниже считывает данные из файла .gzip.
# Read gzip-compressed CSV
census_data = pl.read_csv("2018_census.csv.gz")
Распространённые ошибки и их устранение
Даже с таким высокопроизводительным движком, как Polars, всё ещё можно столкнуться с проблемами, особенно при чтении CSV. Ниже перечислены частые случаи, с которыми мне приходилось сталкиваться, и способы их решения.
-
Ошибки кодировки: вы можете увидеть ошибку
UnicodeDecodeError, что означает, что файл не в кодировке UTF-8 — типичная ситуация для старых файлов или CSV, экспортированных из некоторых версий Excel. Установите подходящую кодировку или используйте"utf8-lossy", если в файле встречаются битые либо неоднородные символы. -
Проблемы с разделителем: если DataFrame загрузился, но все данные оказались в одном столбце, Polars не распознал разделитель. Укажите корректный разделитель явно через аргумент
separator, например точку с запятой (;), табуляцию (\t) или вертикальную черту (|). -
Некорректные типы данных: иногда Polars может неверно вывести типы столбцов, например прочитать числовые ID как строки или столкнуться с ошибками парсинга. В таких случаях используйте
schema_overrides, чтобы задать типы для конкретных столбцов. Если нужно определить типы для всех столбцов, используйтеschema. Также можно повыситьinfer_schema_length, чтобы Polars проанализировал больше строк перед выводом схемы. -
Проблемы памяти на больших файлах: если процесс Python падает при загрузке большого файла, значит, исчерпана оперативная память. Переключитесь с
read_csv()наscan_csv()для ленивой загрузки, чтобы снизить потребление памяти и повысить производительность. Также можно загрузить меньше столбцов или использовать потоковое выполнение, чтобы обрабатывать данные по частям.
Заключение
Функция read_csv() в Polars проста в использовании, но достаточно мощна для задач из реальной практики. На наш взгляд, Polars имеет явное преимущество при работе с растущими наборами данных.
Далее рекомендуем наш блог о движке Polars на GPU, чтобы узнать больше о его возможностях. Готовы к практике? Тогда наш код-алонг «Super Bowl Analytics with Polars» поможет решать реальные аналитические задачи, выполнять вычисления и применять базовые методы ML к задачам спортивной аналитики.
FAQs
В чём разница между read_csv() и scan_csv() в Polars?
read_csv() загружает данные в память немедленно, тогда как scan_csv() использует ленивое выполнение и обрабатывает данные только при вызове .collect().
Когда лучше использовать scan_csv(), а не read_csv()?
Используйте scan_csv() для больших наборов данных или при цепочках преобразований — он оптимизирует выполнение и снижает использование памяти.
Может ли Polars читать только определённые столбцы из CSV?
Да. Используйте параметр columns=[...] в read_csv() или выбирайте столбцы в ленивом запросе с scan_csv().
Как обрабатывать пропущенные значения в CSV-файлах Polars?
По умолчанию Polars считает пустые значения null, а также можно определить собственные маркеры пропусков через null_values=.
Поддерживает ли Polars сжатые CSV-файлы?
Да, поддерживаются сжатые форматы, такие как .gz и .zip, без ручной распаковки.