2026, Jan 07 09:03
Разбиение столбца в Polars на вложенные списки с list.eval
Разбираем строковый столбец в Polars в List[List[str]]: сначала split по переводу строки, затем list.eval и pl.element(). Примеры индексации и приведения типов.
Когда в столбце в виде одной строки хранится многострочный, разделённый запятыми набор данных, часто нужно разбить его на вложенный список, с которым удобно индексироваться и работать дальше по пайплайну. В Polars одного разделения недостаточно: вы получаете список строк, а не список списков. Секрет — выполнить второе разбиение уже внутри каждого элемента списка.
Минимальный пример и подводный камень
Рассмотрим DataFrame с одной строкой, где одна ячейка содержит несколько строк в стиле CSV. Простое разбиение по символу новой строки формирует только внешний список и останавливается до шага с запятыми.
frame = pl.DataFrame({"payload": "A,B,C,1\nD,E,F,2\nG,H,I,3\nJ,K,L,4"})
attempt = frame.with_columns(
pl.col("payload").str.split("\n")
)
Это даёт список строк, но не список списков полей.
Почему так происходит
.str.split("\n") превращает строку в List[str], где каждый элемент — отдельная строка. Чтобы разделить каждую строку по запятой, операцию нужно выполнить на уровне элемента внутри этого списка. Именно это делает list.eval вместе с pl.element(). Также обратите внимание: в этом примере в одной строке смешаны строки и числа; Polars не поддерживает смешанные типы в списке, поэтому числа должны оставаться строками.
Решение с list.eval и логикой на уровне элемента
Используйте вложенное разбиение: сначала по переводу строки, чтобы получить строки, затем внутри list.eval выполните разделение каждого элемента по запятой. В результате получится List[List[str]].
resolved = frame.with_columns(
pl.col("payload")
.str.split("\n")
.list.eval(
pl.element().str.split(",")
)
)
Теперь каждая строка разбита на поля, а столбец содержит список списков, готовый к индексации или дальнейшим преобразованиям. Если планируете удобно использовать эти списки из других столбцов, имеет смысл преобразовать их в столбец-структуру и распаковать (unnest), чтобы получить плоские колонки.
Индексация во вложенный список
Если нужно извлечь конкретное значение и привести его к нужному типу, проиндексируйте вложенный список и выполните преобразование. Ниже небольшой пример: извлекается четвёртое поле третьего внутреннего списка и приводится к Int64.
demo = pl.DataFrame(
{"payload": [[
["A", "B", "C", "1"],
["D", "E", "F", "2"],
["G", "H", "I", "3"],
["J", "K", "L", "4"]
]]},
strict=False
)
picked = demo.with_columns(
pick_value = pl.col("payload").list[2].list[3].cast(pl.Int64)
)
Зачем это важно
В конвейерах разбора строк в Polars данные часто приходят в виде монолитного столбца. Раннее преобразование в корректную вложенную структуру делает последующие преобразования предсказуемыми и типобезопасными. Понимание, что списки со смешанными типами не поддерживаются, помогает избежать скрытых проблем со схемой; оставляйте числа строками или приводите тип при извлечении, чтобы не было сюрпризов. Когда конечная цель — табличные поля, преобразование вложенной структуры в struct и распаковка помогает получить чистые, плоские столбцы.
Вывод
Разбивая столбец в Polars на список списков, мыслите в два этапа: разделите внешний слой, затем выполните разбиение на уровне элемента внутри списка через list.eval и pl.element(). Помните, что списки не могут смешивать типы, поэтому приводите их выборочно при извлечении. Если следующий шаг — столбцовые операции, рассмотрите преобразование в struct и распаковку, чтобы работать с плоскими, чётко типизированными колонками.