Как вы итерацию через различные значения столбца в большом Pyspark Dataframe? .distinct (). Collect () вызывает большое предупреждение задачи

голоса
0

Я пытаюсь перебирать все различные значения в столбце большого Pyspark Dataframe. Когда я пытаюсь сделать это с помощью .distinct (). Collect () это поднимает «задачу слишком большой» предупреждение, даже если есть только два различных значения. Вот некоторые примеры кода:

import pandas as pd
import numpy as np
from pyspark.sql import SparkSession
import pyarrow as pa

spark = SparkSession.builder.appName('Basics').getOrCreate()
spark.conf.set(spark.sql.execution.arrow.enabled, 'true')
length = 200000
table_data = pd.DataFrame({'a': np.random.randint(2,size = length), 'b': np.random.randint(2,size = length),'c': np.random.randint(2,size = length)})

data = spark.createDataFrame(table_data)

for x in data.select(a).distinct().collect():
    data = data.filter(a == '+str(x[0])+')

Этот код создает это предупреждение, которое относится к линии «для й в data.select (» а «) различно () Collect ()..»:

20/01/13 20:39:01 WARN TaskSetManager: Stage 0 contains a task of very large size (154 KB). The maximum recommended task size is 100 KB.

Как вы можете перебирать различные значения в столбце большого Pyspark Dataframe, не сталкиваясь проблемы с памятью?

Задан 13/01/2020 в 23:54
источник пользователем
На других языках...                            


2 ответов

голоса
0

Как вы уже знаете, .collect()это не лучшая практика. Потому что, это действие , которое передать все данные от исполнителей к водителю. Так, в большом dataframe с большим количеством различных значений, то собирать не будет работать вообще. Корневая проблема заключается в том , что вы хотите , чтобы принести все распределенные данные из исполнителей JVM в PVM драйвера.

В высоком уровне, работа вокруг вашей проблемы может быть обменной память с диском.

Вы можете написать dataframe с различными значениями в одном формате CSV, а затем прочитать его снова построчно с Python или панд *:

data.select("a").distinct().coalesce(1).write.csv("temp.csv")
# Specifically, it's a directory with one csv.

С помощью этого решения вы не будете иметь никаких проблем с памятью.

* Есть много решений о том, как читать большой CSV с Python или панд.

Ответил 15/01/2020 в 00:37
источник пользователем

голоса
0

Предупреждение:

20/01/13 20:39:01 WARN TaskSetManager: Стадия 0 содержит задачу очень большого размера (154 КБ). Максимальный рекомендуемый размер задача 100 Кб.

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

pd.DataFrame({'a': np.random.randint(2,size = length), 'b': np.random.randint(2,size = length),'c': np.random.randint(2,size = length)})

Теперь проблема заключается в том , что размер этого dataframe превышает размер разрешенного размера задачи , которая 100Кб. Вы можете получить размер из table_dataс:

table_data.info(memory_usage='deep')

Это должно дать вам примерно 4.6MB = 4710.4KB. В вашем случае размер задача 154КБ , из которого можно сделать вывод о том , что набор данных имеет 4710/154 ~ 30 разделов (пожалуйста , подтвердите , если это возможно с data.rdd.getNumPartitions()).

Решение может быть передел к более высокому числу, чтобы иметь меньший размер задачи <= 100KB то есть: 4710/50 = 94.2KB. Ваш последний запрос должен выглядеть следующим:

data.repartition(50).select("a").distinct().collect()

То, что произошло сейчас, что мы разделили начальный набор данных до 50 разделов, что приводит к значительно меньшему объему данных для каждой задачи (~ 94Kb, как мы видели выше).

Ответил 29/01/2020 в 19:10
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more