Запись DataFrames как разделенного объекта паркета в Polars с помощью PyArrow

У меня есть 12 файлов паркета в каталоге с соответствующими столбцами, которые я пытаюсь записать в секционированный объект с помощью Polars и PyArrow. Я перебираю каждый файл в каталоге и читаю его как LazyFrame. Затем я перебираю список DataFrames и записываю их в секционированный объект. Предполагаемый размер каждого DataFrame составляет ~ 1 ГБ, а все объединенные DataFrame ~ 10 ГБ. Процесс использует ~15 ГБ ОЗУ и завершается менее чем за час.

Я попытался сделать это с помощью следующего кода:

all_lazyframes: list[pl.LazyFrame] = []

for file in glob.glob(input_path):
    lazyframe: pl.LazyFrame = pl.scan_parquet(file)
    all_lazyframes.append(lazyframe)

dataframes: list[pl.DataFrame] = pl.collect_all(all_lazyframes)

for output in dataframes:
    output.write_parquet(
        output_path,
        use_pyarrow=True,
        pyarrow_options = {"partition_cols": ["part"]},
    )

Результирующий секционированный объект имеет следующую структуру:

partitioned_object/
  part=a/
       data0.parquet
       data1.parquet
       ...
  part=b/
       data0.parquet
       data1.parquet
    ...

Размер этого объекта составляет ~250 ГБ. Мой вопрос: почему разделенный объект такой большой, если общий размер входных данных составляет всего ~ 10 ГБ? Есть ли более эффективный способ добиться этого?

Я предполагаю, что там масса новых файлов, верно?

Dean MacGregor 23.09.2023 16:54

В каждом разделе по 13 файлов паркета, всего 26.

Stephen Nicholson 23.09.2023 22:30

Итак, вы переходите от 12 файлов, занимающих в общей сложности 10 ГБ, к 26 файлам, занимающим в общей сложности 250 ГБ? Поначалу я предполагал, что у вас так много файлов, что эффективность сжатия теряется, и вам мешает накопление метаданных. Поскольку вы получаете файлы чуть более чем в два раза больше, я бы не подумал, что это объясняет увеличение размера в 25 раз, если только я чего-то не упускаю. Вы можете сравнить файлы с этим arrow.apache.org/docs/python/generated/…

Dean MacGregor 24.09.2023 03:47

ВВЕДЕНИЕ ПАРКЕТА МЕТАДАТЫ: <PYARROW._PARQUET.FILEMETADATA Объект по адресу 0x108892200> Create_by: Parquet-cpp-arrow версия 10.0.1 num_columns: 14 num_row Объект _parquet.FileMetaData по адресу 0x108892200> создано: parquet-cpp-arrow версия 13.0.0 num_columns: 13 num_rows: 5000000 num_row_groups: 306 format_version: 2.6 serialized_size: 297097

Stephen Nicholson 24.09.2023 14:14
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
4
69
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я решил эту проблему, указав размер строк для каждой группы в функции ds.write_dataset(). Метод поляр в настоящее время занимает больше времени, и вы не можете указать количество строк в группе при использовании параметра PyArrow.

ds.write_dataset(
        data,
        output_path,
        format = "parquet",
        min_rows_per_group=1000000,
        max_rows_per_group=1000000,
        partitioning=ds.partitioning(pa.schema([("type", pa.string())])),
        existing_data_behavior = "overwrite_or_ignore"
    )

Метод Polars занимает больше времени, а опция row_group_size не работает при использовании параметров PyArrow:

    output.write_parquet(
       file=output_path,
       use_pyarrow=True,
       pyarrow_options = {"partition_cols": partition_cols},
       row_group_size=1000000,
    )

Это работает, если вы передадите его через pyarrow_options dict

Dean MacGregor 24.09.2023 19:47

Другие вопросы по теме